トレースビューアー
はじめに
Playwrightトレースビューアーは、スクリプト実行後に記録されたPlaywrightトレースを探索するのに役立つGUIツールです。トレースは、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/fa874b0d59cdedec675521c21124e93161d66533.zip
トレースの記録
トレースは、BrowserContext.Tracing APIを使用して次のように記録できます。
- 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()
{
// This will produce e.g.:
// 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()
{
// This will produce e.g.:
// 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.dokyumento.jp/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.dokyumento.jp/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スナップショットの変化を視覚的に確認できます。時間を前後して、アクションをクリックして検査およびデバッグできます。「Before」タブと「After」タブを使用して、アクションの前後で何が起こったかを視覚的に確認できます。
各アクションを選択すると表示されるもの:
- アクションスナップショット
- アクションログ
- ソースコードの場所
スクリーンショット
スクリーンショットオプションがオンの場合(デフォルト)、各トレースはスクリーンキャストを記録し、それをフィルムストリップとしてレンダリングします。フィルムストリップにカーソルを合わせると、各アクションと状態の拡大画像が表示され、検査したいアクションを簡単に見つけることができます。
アクションをダブルクリックすると、そのアクションの時間範囲が表示されます。タイムラインのスライダーを使用して選択されたアクションを増やし、それらはアクションタブに表示され、すべてのコンソールログとネットワークログは選択されたアクションのログのみを表示するようにフィルタリングされます。
スナップショット
スナップショットオプションがオンの場合(デフォルト)、Playwrightは各アクションに対して一連の完全なDOMスナップショットをキャプチャします。アクションのタイプに応じて、次をキャプチャします。
タイプ | 説明 |
---|---|
前 | アクションが呼び出された時点のスナップショット。 |
アクション | 実行された入力の瞬間のスナップショット。このタイプのスナップショットは、Playwrightが正確にどこをクリックしたかを探索する際に特に役立ちます。 |
後 | アクション後のスナップショット。 |
典型的なアクションスナップショットは次のようになります。
DOMノードと正確なクリック位置の両方がハイライト表示されていることに注目してください。
ソース
サイドバーのアクションをクリックすると、そのアクションのコード行がソースパネルでハイライト表示されます。
呼び出し
呼び出しタブには、アクションにかかった時間、使用されたロケーター、厳密モードであったか、使用されたキーなどのアクションに関する情報が表示されます。
ログ
テストの完全なログを確認して、Playwrightが背後で行っていること(ビューへのスクロール、要素が可視、有効、安定になるまでの待機、クリック、入力、キー操作などのアクションの実行など)をよりよく理解できます。
エラー
テストが失敗した場合、エラータブに各テストのエラーメッセージが表示されます。タイムラインにはエラーが発生した場所を示す赤い線も表示されます。ソースタブをクリックして、ソースコードのどの行でエラーが発生したかを確認することもできます。
コンソール
ブラウザとテストの両方からのコンソールログを確認できます。コンソールログがブラウザから来たのか、テストファイルから来たのかを示すために、異なるアイコンが表示されます。
アクションサイドバーでテストのアクションをダブルクリックします。これにより、そのアクション中に作成されたログのみが表示されるようにコンソールがフィルタリングされます。すべて表示ボタンをクリックすると、すべてのコンソールログが再度表示されます。
タイムラインを使用して、開始点をクリックし、終了点までドラッグすることでアクションをフィルタリングします。コンソールタブも、選択されたアクション中に作成されたログのみを表示するようにフィルタリングされます。
ネットワーク
ネットワークタブには、テスト中に作成されたすべてのネットワークリクエストが表示されます。さまざまなタイプのリクエスト、ステータスコード、メソッド、リクエスト、コンテンツタイプ、期間、サイズでソートできます。リクエストをクリックすると、リクエストヘッダー、レスポンスヘッダー、リクエストボディ、レスポンスボディなど、より詳しい情報が表示されます。
アクションサイドバーでテストのアクションをダブルクリックします。これにより、そのアクション中に作成されたリクエストのみが表示されるようにネットワークリクエストがフィルタリングされます。すべて表示ボタンをクリックすると、すべてのネットワークリクエストが再度表示されます。
タイムラインを使用して、開始点をクリックし、終了点までドラッグすることでアクションをフィルタリングします。ネットワークタブも、選択されたアクション中に作成されたネットワークリクエストのみを表示するようにフィルタリングされます。
メタデータ
アクションタブの隣にはメタデータタブがあり、ブラウザ、ビューポートサイズ、テストの実行時間など、テストに関する詳細情報が表示されます。