メインコンテンツへスキップ

スナップショットテスト

概要

Playwrightのスナップショットテストでは、ページのアクセシビリティツリーを事前定義されたスナップショットテンプレートに対してアサートできます。

await page.GotoAsync("https://playwright.dokyumento.jp/");
await Expect(page.Locator("banner")).ToMatchAriaSnapshotAsync(@"
- banner:
- heading ""Playwright enables reliable end-to-end testing for modern web apps."" [level=1]
- link ""Get started""
- link ""Star microsoft/playwright on GitHub""
- link /[\\d]+k\\+ stargazers on GitHub/
");

アサーションテストとスナップショットテスト

スナップショットテストとアサーションテストは、テスト自動化において異なる目的を果たします

アサーションテスト

アサーションテストは、要素やコンポーネントに関する特定の値や条件をアサートする、対象を絞ったアプローチです。例えば、Playwrightでは、`Expect(Locator).ToHaveTextAsync()`は要素が期待されるテキストを含んでいることを検証し、`Expect(Locator).ToHaveValueAsync()`は入力フィールドが期待される値を持っていることを確認します。アサーションテストは具体的であり、一般的に要素やプロパティの現在の状態を、期待される事前定義された状態と照合します。予測可能な単一値のチェックには効果的ですが、より広範な構造やバリエーションをテストする際にはスコープが限定されます。

利点

  • 明確さ: テストの意図が明確で理解しやすい。
  • 特異性: テストは機能の特定の側面に焦点を当て、関連性のない変更に対してより堅牢にします。
  • デバッグ: 失敗は、問題のある側面を直接指摘する的を絞ったフィードバックを提供します。

欠点

  • 複雑な出力に対する冗長性: 複雑なデータ構造や大きな出力に対してアサーションを記述することは、面倒でエラーが発生しやすくなります。
  • メンテナンスのオーバーヘッド: コードが進化するにつれて、アサーションを手動で更新するのに時間がかかる場合があります。

スナップショットテスト

スナップショットテストは、特定の時点における要素、コンポーネント、またはデータの全体の状態の「スナップショット」または表現をキャプチャし、将来の比較のために保存します。テストを再実行する際、現在の状態がスナップショットと比較され、違いがあればテストは失敗します。このアプローチは、各詳細を手動でアサートするには時間がかかりすぎるような、複雑なまたは動的な構造に特に役立ちます。スナップショットテストは、アサーションテストよりも広範で全体的であり、時間の経過とともに発生するより複雑な変更を追跡できます。

利点

  • 複雑な出力を簡素化: 例えば、UIコンポーネントのレンダリングされた出力をテストすることは、従来のアサーションでは面倒です。スナップショットは、比較を容易にするために出力全体をキャプチャします。
  • 迅速なフィードバックループ: 開発者は、出力における意図しない変更を簡単に見つけることができます。
  • 一貫性を促進: コードの進化に合わせて、一貫した出力を維持するのに役立ちます。

欠点

  • 過度の依存: スナップショットの変更を完全に理解せずに受け入れてしまいがちで、バグを隠してしまう可能性があります。
  • 粒度: 差異が発生した場合、特に軽微な変更が出力の大部分に影響する場合、大きなスナップショットは解釈が難しい場合があります。
  • 適合性: 出力が頻繁にまたは予測不能に変化する、非常に動的なコンテンツには理想的ではありません。

使用する場面

  • スナップショットテストは以下の用途に最適です
    • ページ全体およびコンポーネントのUIテスト。
    • 複雑なUIコンポーネントの広範な構造チェック。
    • 構造がめったに変わらない出力に対する回帰テスト。
  • アサーションテストは以下の用途に最適です
    • コアロジックの検証。
    • 計算値のテスト。
    • 正確な条件を必要とするきめ細かいテスト。

広範な構造チェックにはスナップショットテストを、特定の機能にはアサーションテストを組み合わせることで、バランスの取れたテスト戦略を実現できます。

Aria スナップショット

Playwrightでは、ariaスナップショットはページのアクセシビリティツリーのYAML表現を提供します。これらのスナップショットは、後で保存および比較して、ページ構造が一貫しているか、または定義された期待を満たしているかを確認できます。

YAML形式は、ページのアクセシブルな要素の階層構造を記述し、ロール属性テキストコンテンツを詳細に示します。構造はツリー状の構文に従い、各ノードはアクセシブルな要素を表し、インデントはネストされた要素を示します。

ツリー内の各アクセシブルな要素はYAMLノードとして表現されます

- role "name" [attribute=value]
  • role: 要素のARIAまたはHTMLロールを指定します (例: heading, list, listitem, button)。
  • "name": 要素のアクセシブルな名前。引用符で囲まれた文字列は厳密な値を示し、/patterns/は正規表現に使用されます。
  • [attribute=value]: 角括弧で囲まれた属性と値は、checked, disabled, expanded, level, pressed, selectedなどの特定のARIA属性を表します。

これらの値はARIA属性から派生するか、HTMLセマンティクスに基づいて計算されます。ページのアクセシビリティツリー構造を検査するには、Chrome DevToolsのアクセシビリティタブを使用します。

スナップショットのマッチング

Playwrightの`Expect(Locator).ToMatchAriaSnapshotAsync()`アサーションメソッドは、ロケータースコープのアクセシブルな構造を事前定義されたariaスナップショットテンプレートと比較し、テスト要件に対するページの検証を支援します。

以下のDOMの場合

<h1>title</h1>

以下のスナップショットテンプレートを使用してマッチングできます

await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@"
- heading ""title""
");

マッチング時、スナップショットテンプレートはページの現在のアクセシビリティツリーと比較されます

  • ツリー構造がテンプレートと一致すればテストは合格し、一致しない場合は失敗し、期待されるアクセシビリティ状態と実際のアクティビティ状態との不一致を示します。
  • 比較は大文字と小文字を区別し、空白文字は圧縮されるため、インデントと改行は無視されます。
  • 比較は順序に敏感であり、スナップショットテンプレート内の要素の順序がページのアクセシビリティツリー内の順序と一致する必要があります。

部分一致

属性やアクセシブルな名前を省略することで、ノードの部分一致を実行できます。これにより、正確な一致を要求することなく、アクセシビリティツリーの特定の部位を検証できます。この柔軟性は、動的な属性や重要でない属性に役立ちます。

<button>Submit</button>

ariaスナップショット

- button

この例では、ボタンのロールは一致しますが、アクセシブルな名前(「Submit」)は指定されていないため、ボタンのラベルに関係なくテストが合格します。


checkeddisabled のようなARIA属性を持つ要素の場合、これらの属性を省略することで部分一致が可能になり、ロールと階層のみに焦点を当てることができます。

<input type="checkbox" checked>

部分一致のためのariaスナップショット

- checkbox

この部分一致では、checked 属性は無視されるため、チェックボックスの状態に関わらずテストは合格します。


同様に、特定のリスト項目やネストされた要素を省略することで、リストやグループ内の子要素を部分的に一致させることができます。

<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

部分一致のためのariaスナップショット

- list
- listitem: Feature B

部分一致により、特定のコンテンツや属性を強制することなく、重要なページ構造を検証する柔軟なスナップショットテストを作成できます。

厳密なマッチング

デフォルトでは、子要素のサブセットを含むテンプレートが一致します

<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

部分一致のためのariaスナップショット

- list
- listitem: Feature B

/children プロパティは、子要素の照合方法を制御するために使用できます

  • contain (デフォルト): 指定されたすべての子が順序通りに存在する場合に一致します
  • equal: 子要素が指定されたリストと順序を含め完全に一致する場合に一致します
  • deep-equal: 子要素が指定されたリストと順序を含め完全に一致し、ネストされた子要素も含む場合に一致します
<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

Feature Cがテンプレートにないため、ariaスナップショットは失敗します

- list
- /children: equal
- listitem: Feature A
- listitem: Feature B

正規表現によるマッチング

正規表現を使用すると、動的または可変のテキストを持つ要素に対して柔軟なマッチングが可能です。アクセシブルな名前とテキストは正規表現パターンをサポートできます。

<h1>Issues 12</h1>

正規表現を使用したariaスナップショット

- heading /Issues \d+/

スナップショットの生成

Playwrightでariaスナップショットを作成することは、アプリケーションの構造を確保し、維持するのに役立ちます。テストのセットアップとワークフローに応じて、さまざまな方法でスナップショットを生成できます。

Playwright コードジェネレーターによるスナップショットの生成

Playwrightのコードジェネレーターを使用している場合、ariaスナップショットの生成は、そのインタラクティブなインターフェースによって効率化されます。

  • 「スナップショットのアサート」アクション: コードジェネレーターでは、「スナップショットのアサート」アクションを使用して、選択した要素のスナップショットアサーションを自動的に作成できます。これは、記録されたテストフローの一部としてariaスナップショットをキャプチャする迅速な方法です。
  • 「Ariaスナップショット」タブ: コードジェネレーターインターフェース内の「Ariaスナップショット」タブは、選択されたロケーターのariaスナップショットを視覚的に表示し、要素のロール、属性、アクセシブルな名前を探索、検査、検証して、スナップショットの作成とレビューを支援します。

Locator.ariaSnapshot メソッドの使用

Locator.AriaSnapshotAsync() メソッドを使用すると、ロケーターのスコープ内のアクセシブルな要素のYAML表現をプログラムで作成できます。これは、テスト実行中にスナップショットを動的に生成するのに特に役立ちます。

:

var snapshot = await page.Locator("body").AriaSnapshotAsync();
Console.WriteLine(snapshot);

このコマンドは、指定されたロケーターのスコープ内のariaスナップショットをYAML形式で出力します。必要に応じてこれを検証または保存できます。

アクセシビリティツリーの例

レベル属性付きの見出し

見出しは、その見出しレベルを示す level 属性を含むことができます。

<h1>Title</h1>
<h2>Subtitle</h2>

ariaスナップショット

- heading "Title" [level=1]
- heading "Subtitle" [level=2]

テキストノード

スタンドアロンまたは説明的なテキスト要素は、テキストノードとして表示されます。

<div>Sample accessible name</div>

ariaスナップショット

- text: Sample accessible name

インライン複数行テキスト

段落などの複数行テキストは、ariaスナップショットで正規化されます。

<p>Line 1<br>Line 2</p>

ariaスナップショット

- paragraph: Line 1 Line 2

リンクは、そのテキストまたは擬似要素から構成されたコンテンツを表示します。

<a href="#more-info">Read more about Accessibility</a>

ariaスナップショット

- link "Read more about Accessibility"

テキストボックス

タイプ text の入力要素は、その value 属性の内容を表示します。

<input type="text" value="Enter your name">

ariaスナップショット

- textbox: Enter your name

項目付きリスト

順序付きリストと順序なしリストには、そのリスト項目が含まれます。

<ul aria-label="Main Features">
<li>Feature 1</li>
<li>Feature 2</li>
</ul>

ariaスナップショット

- list "Main Features":
- listitem: Feature 1
- listitem: Feature 2

グループ化された要素

グループは、サマリーコンテンツを持つ <details> 要素などのネストされた要素をキャプチャします。

<details>
<summary>Summary</summary>
<p>Detail content here</p>
</details>

ariaスナップショット

- group: Summary

属性と状態

checkeddisabledexpandedlevelpressedselected などの一般的に使用されるARIA属性は、コントロールの状態を表します。

checked 属性を持つチェックボックス

<input type="checkbox" checked>

ariaスナップショット

- checkbox [checked]

pressed 属性を持つボタン

<button aria-pressed="true">Toggle</button>

ariaスナップショット

- button "Toggle" [pressed=true]