Просмотрщик трассировок
Введение
Playwright Trace Viewer — это графический инструмент, который помогает исследовать записанные трассировки Playwright после выполнения скрипта. Трассировки — отличный способ отладки ваших тестов, когда они не проходят в CI. Вы можете открыть трассировки локально или в вашем браузере на trace.playwright.dev.
Открытие просмотрщика трассировок
Вы можете открыть сохраненную трассировку с помощью Playwright CLI или в браузере на trace.playwright.dev. Убедитесь, что вы добавили полный путь к файлу trace.zip
.
pwsh bin/Debug/netX/playwright.ps1 show-trace trace.zip
Использование trace.playwright.dev
trace.playwright.dev — это статически размещенный вариант просмотрщика трассировок. Вы можете загрузить файлы трассировки, перетащив их или используя кнопку Выбрать файл(ы)
.
Просмотрщик трассировок загружает трассировку полностью в ваш браузер и не передает данные внешним ресурсам.

Просмотр удаленных трассировок
Вы можете открыть удаленные трассировки напрямую, используя их URL. Это упрощает просмотр удаленной трассировки без необходимости вручную загружать файл из CI, например.
pwsh bin/Debug/netX/playwright.ps1 show-trace https://example.com/trace.zip
При использовании trace.playwright.dev вы также можете передать URL вашей загруженной трассировки из доступного хранилища (например, внутри вашего CI) в качестве параметра запроса. Могут применяться правила CORS (Cross-Origin Resource Sharing).
https://trace.playwright.dev/?trace=https://demo.playwright.dev/reports/todomvc/data/cb0fa77ebd9487a5c899f3ae65a7ffdbac681182.zip
Запись трассировки
Трассировки могут быть записаны с использованием API BrowserContext.Tracing следующим образом:
- MSTest
- NUnit
- xUnit
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class Tests : PageTest
{
[SetUp]
public async Task Setup()
{
await Context.Tracing.StartAsync(new()
{
Title = TestContext.CurrentContext.Test.ClassName + "." + TestContext.CurrentContext.Test.Name,
Screenshots = true,
Snapshots = true,
Sources = true
});
}
[TearDown]
public async Task TearDown()
{
// Это создаст, например:
// bin/Debug/net8.0/playwright-traces/PlaywrightTests.Tests.Test1.zip
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
TestContext.CurrentContext.WorkDirectory,
"playwright-traces",
$"{TestContext.CurrentContext.Test.ClassName}.{TestContext.CurrentContext.Test.Name}.zip"
)
});
}
[Test]
public async Task TestYourOnlineShop()
{
// ..
}
}
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.MSTest;
namespace PlaywrightTestsMSTest;
[TestClass]
public class UnitTest1 : PageTest
{
[TestInitialize]
public async Task TestInitialize()
{
await Context.Tracing.StartAsync(new()
{
Title = TestContext.TestName,
Screenshots = true,
Snapshots = true,
Sources = true
});
}
[TestCleanup]
public async Task TestCleanup()
{
// Это создаст, например:
// bin/Debug/net8.0/playwright-traces/PlaywrightTests.UnitTest1.zip
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{TestContext.FullyQualifiedTestClassName}.zip"
)
});
}
[TestMethod]
public async Task TestYourOnlineShop()
{
// ...
}
}
using System.Reflection;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using Xunit.Sdk;
namespace PlaywrightTests;
[WithTestName]
public class UnitTest1 : PageTest
{
public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
)
});
await base.DisposeAsync().ConfigureAwait(false);
}
[Fact]
public async Task GetStartedLink()
{
// ...
await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}
Это запишет трассировку и поместит ее в директорию bin/Debug/net8.0/playwright-traces/
.
Запуск трассировки только при сбое
Настройте ваши тесты так, чтобы записывать трассировку только в случае сбоя теста:
- MSTest
- NUnit
- xUnit
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class ExampleTest : PageTest
{
[SetUp]
public async Task Setup()
{
await Context.Tracing.StartAsync(new()
{
Title = $"{TestContext.CurrentContext.Test.ClassName}.{TestContext.CurrentContext.Test.Name}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
[TearDown]
public async Task TearDown()
{
var failed = TestContext.CurrentContext.Result.Outcome == NUnit.Framework.Interfaces.ResultState.Error
|| TestContext.CurrentContext.Result.Outcome == NUnit.Framework.Interfaces.ResultState.Failure;
await Context.Tracing.StopAsync(new()
{
Path = failed ? Path.Combine(
TestContext.CurrentContext.WorkDirectory,
"playwright-traces",
$"{TestContext.CurrentContext.Test.ClassName}.{TestContext.CurrentContext.Test.Name}.zip"
) : null,
});
}
[Test]
public async Task GetStartedLink()
{
// ..
}
}
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.MSTest;
namespace PlaywrightTests;
[TestClass]
public class ExampleTest : PageTest
{
[TestInitialize]
public async Task TestInitialize()
{
await Context.Tracing.StartAsync(new()
{
Title = $"{TestContext.FullyQualifiedTestClassName}.{TestContext.TestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
[TestCleanup]
public async Task TestCleanup()
{
var failed = new[] { UnitTestOutcome.Failed, UnitTestOutcome.Error, UnitTestOutcome.Timeout, UnitTestOutcome.Aborted }.Contains(TestContext.CurrentTestOutcome);
await Context.Tracing.StopAsync(new()
{
Path = failed ? Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{TestContext.FullyQualifiedTestClassName}.{TestContext.TestName}.zip"
) : null,
});
}
[TestMethod]
public async Task GetStartedLink()
{
// ...
}
}
using System.Reflection;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using Xunit.Sdk;
namespace PlaywrightTests;
[WithTestName]
public class UnitTest1 : PageTest
{
public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
await Context.Tracing.StopAsync(new()
{
Path = !TestOk ? Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
) : null
});
await base.DisposeAsync().ConfigureAwait(false);
}
[Fact]
public async Task GetStartedLink()
{
// ...
await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}
Функции просмотрщика трассировок
Действия
На вкладке Действия вы можете увидеть, какой локатор использовался для каждого действия и сколько времени заняло его выполнение. Наведите курсор на каждое действие вашего теста и визуально увидите изменения в снимке DOM. Перемещайтесь назад и вперед во времени и нажимайте на действие, чтобы исследовать и отлаживать. Используйте вкладки До и После, чтобы визуально увидеть, что произошло до и после действия.
Выбор каждого действия показывает:
- Снимки действия
- Журнал действий
- Местоположение исходного кода
Скриншоты
При трассировке с включенной опцией Screenshots (по умолчанию), каждая трассировка записывает видеозапись и отображает ее в виде пленочной полосы. Вы можете навести курсор на пленочную полосу, чтобы увидеть увеличенное изображение для каждого действия и состояния, что поможет вам легко найти действие, которое вы хотите исследовать.
Дважды щелкните по действию, чтобы увидеть временной диапазон для этого действия. Вы можете использовать ползунок на временной шкале, чтобы увеличить количество выбранных действий, и они будут показаны на вкладке Действия, а все журналы консоли и сети будут отфильтрованы, чтобы показывать только журналы для выбранных действий.
Снимки
При трассировке с включенной опцией Snapshots (по умолчанию), Playwright захватывает набор полных снимков DOM для каждого действия. В зависимости от типа действия, он будет захватывать:
Тип | Описание |
---|---|
До | Снимок на момент вызова действия. |
Действие | Снимок в момент выполнения ввода. Этот тип снимка особенно полезен при исследовании, где именно Playwright кликнул. |
После | Снимок после действия. |
Вот как выглядит типичный снимок Действия:
Обратите внимание, как он выделяет как DOM-узел, так и точное место клика.
Исходный код
Когда вы нажимаете на действие в боковой панели, строка кода для этого действия выделяется в панели исходного кода.
Вызов
Вкладка вызова показывает информацию о действии, такую как время выполнения, какой локатор использовался, если в строгом режиме, и какой ключ использовался.
Журнал
Просмотрите полный журнал вашего теста, чтобы лучше понять, что Playwright делает за кулисами, например, прокручивает в видимую область, ожидает, пока элемент станет видимым, включенным и стабильным, и выполняет действия, такие как клик, заполнение, нажатие и т.д.
Ошибки
Если ваш тест не проходит, вы увидите сообщения об ошибках для каждого теста на вкладке Ошибки. Временная шкала также покажет красную линию, подчеркивающую, где произошла ошибка. Вы также можете нажать на вкладку исходного кода, чтобы увидеть, на какой строке исходного кода произошла ошибка.
Консоль
Просмотрите журналы консоли из браузера, а также из вашего теста. Различные значки отображаются, чтобы показать, пришел ли журнал консоли из браузера или из тестового файла.
Дважды щелкните по действию из вашего теста в боковой панели действий. Это отфильтрует консоль, чтобы показывать только журналы, которые были сделаны во время этого действия. Нажмите кнопку Показать все, чтобы снова увидеть все журналы консоли.
Используйте временную шкалу для фильтрации действий, нажав на начальную точку и перетащив до конечной точки. Вкладка консоли также будет отфильтрована, чтобы показывать только журналы, которые были сделаны во время выбранных действий.
Сеть
Вкладка Сеть показывает все сетевые запросы, которые были сделаны во время вашего теста. Вы можете сортировать по различным типам запросов, коду состояния, методу, запросу, типу контента, продолжительности и размеру. Нажмите на запрос, чтобы увидеть больше информации о нем, такую как заголовки запроса, заголовки ответа, тело запроса и тело ответа.
Дважды щелкните по действию из вашего теста в боковой панели действий. Это отфильтрует сетевые запросы, чтобы показывать только запросы, которые были сделаны во время этого действия. Нажмите кнопку Показать все, чтобы снова увидеть все сетевые запросы.
Используйте временную шкалу для фильтрации действий, нажав на начальную точку и перетащив до конечной точки. Вкладка сети также будет отфильтрована, чтобы показывать только сетевые запросы, которые были сделаны во время выбранных действий.
Метаданные
Рядом с вкладкой Действия вы найдете вкладку Метаданные, которая покажет вам больше информации о вашем тесте, такую как браузер, размер окна просмотра, продолжительность теста и многое другое.