スナップショットテスト
概要
Playwrightのスナップショットテストを使用すると、ページのアクセシビリティツリーを事前定義されたスナップショットテンプレートに対してアサートできます。
page.navigate("https://playwright.dokyumento.jp/");
assertThat(page.locator("banner")).matchesAriaSnapshot("""
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
""");
アサーションテストとスナップショットテストの比較
スナップショットテストとアサーションテストは、テスト自動化において異なる目的を果たします。
アサーションテスト
アサーションテストは、要素やコンポーネントに関する特定の値や条件をアサートする、的を絞ったアプローチです。たとえば、Playwrightでは、assertThat(locator).hasText() は要素が期待されるテキストを含んでいることを検証し、assertThat(locator).hasValue() は入力フィールドが期待される値を持っていることを確認します。アサーションテストは具体的であり、一般的に要素やプロパティの現在の状態を、期待される事前定義された状態と照合します。予測可能で単一値のチェックには適していますが、より広範な構造やバリエーションをテストする際には範囲が限定されます。
利点
- 明確性: テストの意図が明確で理解しやすい。
- 具体性: テストが特定の機能面に焦点を当てるため、無関係な変更に対してより堅牢です。
- デバッグ: 失敗時には的を絞ったフィードバックが提供され、問題のある側面を直接示します。
欠点
- 複雑な出力に対する冗長性: 複雑なデータ構造や大量の出力に対するアサーションの記述は、面倒でエラーが発生しやすい場合があります。
- メンテナンスのオーバーヘッド: コードが進化するにつれて、アサーションを手動で更新するのに時間がかかる場合があります。
スナップショットテスト
スナップショットテストは、要素、コンポーネント、またはデータの特定の時点での全体の状態の「スナップショット」または表現をキャプチャし、その後の比較のために保存します。テストを再実行すると、現在の状態がスナップショットと比較され、違いがある場合はテストが失敗します。このアプローチは、手動で各詳細をアサートすると時間がかかりすぎる複雑または動的な構造に特に役立ちます。スナップショットテストはアサーションテストよりも広範で全体的であり、時間の経過とともに複雑な変更を追跡できます。
利点
- 複雑な出力を簡素化: たとえば、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の[Accessibility]タブを使用します。
スナップショットの一致
PlaywrightのassertThat(locator).matchesAriaSnapshot()
アサーションメソッドは、ロケータスコープのアクセシブルな構造を事前定義されたariaスナップショットテンプレートと比較し、ページのテスト要件に対する状態の検証に役立ちます。
次のDOMの場合
<h1>title</h1>
次のスナップショットテンプレートを使用して一致させることができます
assertThat(page.locator("body")).matchesAriaSnapshot("""
- heading "title"
""");
一致させる際、スナップショットテンプレートはページの現在のアクセシビリティツリーと比較されます
- ツリー構造がテンプレートと一致すればテストは合格し、そうでなければ失敗します。これは、期待されるアクセシビリティの状態と実際の状態との間に不一致があることを示します。
- 比較は大文字と小文字を区別し、空白を圧縮するため、インデントと改行は無視されます。
- 比較は順序に敏感です。つまり、スナップショットテンプレート内の要素の順序は、ページのアクセシビリティツリー内の順序と一致する必要があります。
部分一致
属性やアクセシブルな名前を省略することで、ノードの部分一致を実行でき、厳密な一致を必要とせずにアクセシビリティツリーの特定のパーツを検証できます。この柔軟性は、動的な属性や重要でない属性に役立ちます。
<button>Submit</button>
ariaスナップショット
- button
この例では、ボタンのロールは一致しますが、アクセシブルな名前 ("Submit") は指定されていないため、ボタンのラベルに関係なくテストが合格します。
checked
や disabled
のような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>
特徴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.ariaSnapshot()
メソッドを使用すると、ロケーターのスコープ内にあるアクセシブルな要素のYAML表現をプログラムで作成できます。これは、テスト実行中にスナップショットを動的に生成する場合に特に役立ちます。
例:
String snapshot = page.locator("body").ariaSnapshot();
System.out.println(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
属性と状態
checked
、disabled
、expanded
、level
、pressed
、selected
などの一般的に使用されるARIA属性は、コントロールの状態を表します。
checked
属性を持つチェックボックス
<input type="checkbox" checked>
ariaスナップショット
- checkbox [checked]
pressed
属性を持つボタン
<button aria-pressed="true">Toggle</button>
ariaスナップショット
- button "Toggle" [pressed=true]