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

アサーション

はじめに

Playwright には、expect 関数の形式でテストアサーションが含まれています。アサーションを行うには、expect(value) を呼び出し、期待を反映するマッチャーを選択します。toEqualtoContaintoBeTruthy など、あらゆる条件をアサートするために使用できる多くの汎用マッチャーがあります。

expect(success).toBeTruthy();

Playwright には、期待される条件が満たされるまで待機するウェブ固有の非同期マッチャーも含まれています。次の例を考えてみましょう。

await expect(page.getByTestId('status')).toHaveText('Submitted');

Playwright は、取得した要素が"Submitted"テキストを持つまで、テスト ID がstatusの要素を再テストします。条件が満たされるかタイムアウトに達するまで、要素を繰り返し再取得してチェックします。このタイムアウトを渡すか、テスト設定のtestConfig.expect値を使用して一度設定できます。

デフォルトでは、アサーションのタイムアウトは 5 秒に設定されています。さまざまなタイムアウトの詳細については、こちらをご覧ください。

自動再試行アサーション

以下のアサーションは、アサーションが成功するか、アサーションタイムアウトに達するまで再試行します。再試行アサーションは非同期であるため、await する必要があることに注意してください。

アサーション説明
await expect(locator).toBeAttached()要素が添付されている
await expect(locator).toBeChecked()チェックボックスがチェックされている
await expect(locator).toBeDisabled()要素が無効になっている
await expect(locator).toBeEditable()要素が編集可能である
await expect(locator).toBeEmpty()コンテナが空である
await expect(locator).toBeEnabled()要素が有効である
await expect(locator).toBeFocused()要素がフォーカスされている
await expect(locator).toBeHidden()要素が非表示である
await expect(locator).toBeInViewport()要素がビューポートと交差している
await expect(locator).toBeVisible()要素が表示されている
await expect(locator).toContainText()要素にテキストが含まれている
await expect(locator).toContainClass()要素に指定されたCSSクラスが含まれる
await expect(locator).toHaveAccessibleDescription()要素に一致するアクセシブルな説明がある
await expect(locator).toHaveAccessibleName()要素に一致するアクセシブルな名前がある
await expect(locator).toHaveAttribute()要素が DOM 属性を持つ
await expect(locator).toHaveClass()要素に指定されたCSSクラスプロパティがある
await expect(locator).toHaveCount()リストが正確な数の子要素を持つ
await expect(locator).toHaveCSS()要素が CSS プロパティを持つ
await expect(locator).toHaveId()要素が ID を持つ
await expect(locator).toHaveJSProperty()要素が JavaScript プロパティを持つ
await expect(locator).toHaveRole()要素に特定のARIAロールがある
await expect(locator).toHaveScreenshot()要素のスクリーンショットがある
await expect(locator).toHaveText()要素がテキストに一致する
await expect(locator).toHaveValue()入力に値がある
await expect(locator).toHaveValues()選択にオプションが選択されている
await expect(locator).toMatchAriaSnapshot()要素がAriaスナップショットと一致する
await expect(page).toHaveScreenshot()ページのスクリーンショットがある
await expect(page).toHaveTitle()ページにタイトルがある
await expect(page).toHaveURL()ページに URL がある
await expect(response).toBeOK()レスポンスが OK ステータスを持つ

非再試行アサーション

これらのアサーションは、任意の条件をテストできますが、自動再試行は行いません。ほとんどの場合、Webページは情報を非同期に表示するため、非再試行アサーションを使用すると不安定なテストにつながる可能性があります。

可能な限り自動再試行アサーションを使用してください。再試行が必要なより複雑なアサーションの場合は、expect.poll または expect.toPass を使用してください。

アサーション説明
expect(value).toBe()値が同じである
expect(value).toBeCloseTo()数値がほぼ等しい
expect(value).toBeDefined()値がundefinedではない
expect(value).toBeFalsy()値がfalsyである(例:false0nullなど)
expect(value).toBeGreaterThan()数値がより大きい
expect(value).toBeGreaterThanOrEqual()数値がより大きいか等しい
expect(value).toBeInstanceOf()オブジェクトがクラスのインスタンスである
expect(value).toBeLessThan()数値がより小さい
expect(value).toBeLessThanOrEqual()数値がより小さいか等しい
expect(value).toBeNaN()値がNaNである
expect(value).toBeNull()値がnullである
expect(value).toBeTruthy()値がtruthyである(つまり、false0nullなどではない)
expect(value).toBeUndefined()値がundefinedである
expect(value).toContain()文字列がサブストリングを含む
expect(value).toContain()配列またはセットが要素を含む
expect(value).toContainEqual()配列またはセットが類似の要素を含む
expect(value).toEqual()値が類似している — ディープ等価性とパターンマッチング
expect(value).toHaveLength()配列または文字列の長さ
expect(value).toHaveProperty()オブジェクトがプロパティを持つ
expect(value).toMatch()文字列が正規表現と一致する
expect(value).toMatchObject()オブジェクトが指定されたプロパティを含む
expect(value).toStrictEqual()プロパティの型を含む値が類似している
expect(value).toThrow()関数がエラーをスローする
expect(value).any()クラス/プリミティブの任意のインスタンスと一致する
expect(value).anything()何でも一致する
expect(value).arrayContaining()配列が特定の要素を含む
expect(value).closeTo()数値がほぼ等しい
expect(value).objectContaining()オブジェクトが特定のプロパティを含む
expect(value).stringContaining()文字列がサブストリングを含む
expect(value).stringMatching()文字列が正規表現と一致する

マッチャーの否定

一般的に、マッチャーの先頭に .not を追加することで、逆が真であると期待できます。

expect(value).not.toEqual(0);
await expect(locator).not.toContainText('some text');

ソフトアサーション

デフォルトでは、アサーションの失敗はテスト実行を終了します。Playwright はソフトアサーションもサポートしています。ソフトアサーションの失敗はテスト実行を**終了させず**、テストを失敗としてマークします。

// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
await expect.soft(page.getByTestId('eta')).toHaveText('1 day');

// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click();
await expect.soft(page.getByRole('heading', { name: 'Make another order' })).toBeVisible();

テスト実行中の任意の時点で、ソフトアサーションの失敗があったかどうかを確認できます。

// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
await expect.soft(page.getByTestId('eta')).toHaveText('1 day');

// Avoid running further if there were soft assertion failures.
expect(test.info().errors).toHaveLength(0);

ソフトアサーションは Playwright テストランナーでのみ機能することに注意してください。

カスタム expect メッセージ

expect 関数の2番目の引数としてカスタム expect メッセージを指定できます。例:

await expect(page.getByText('Name'), 'should be logged in').toBeVisible();

このメッセージは、アサーションに関するより多くのコンテキストを提供し、成功した期待と失敗した期待の両方でレポーターに表示されます。

expect が成功した場合、次のような成功ステップが表示されることがあります。

✅ should be logged in    @example.spec.ts:18

expect が失敗した場合、エラーは次のようになります。

    Error: should be logged in

Call log:
- expect.toBeVisible with timeout 5000ms
- waiting for "getByText('Name')"


2 |
3 | test('example test', async({ page }) => {
> 4 | await expect(page.getByText('Name'), 'should be logged in').toBeVisible();
| ^
5 | });
6 |

ソフトアサーションもカスタムメッセージをサポートしています。

expect.soft(value, 'my soft assertion').toBe(56);

expect.configure

timeoutsoft などの独自のデフォルト値を持つ独自の事前設定された expect インスタンスを作成できます。

const slowExpect = expect.configure({ timeout: 10000 });
await slowExpect(locator).toHaveText('Submit');

// Always do soft assertions.
const softExpect = expect.configure({ soft: true });
await softExpect(locator).toHaveText('Submit');

expect.poll

expect.poll を使用すると、任意の同期 expect を非同期ポーリングのものに変換できます。

次のメソッドは、HTTP ステータス 200 を返すまで指定された関数をポーリングします。

await expect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}, {
// Custom expect message for reporting, optional.
message: 'make sure API eventually succeeds',
// Poll for 10 seconds; defaults to 5 seconds. Pass 0 to disable timeout.
timeout: 10000,
}).toBe(200);

カスタムポーリング間隔も指定できます。

await expect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}, {
// Probe, wait 1s, probe, wait 2s, probe, wait 10s, probe, wait 10s, probe
// ... Defaults to [100, 250, 500, 1000].
intervals: [1_000, 2_000, 10_000],
timeout: 60_000
}).toBe(200);

expect.configure({ soft: true }) と expect.poll を組み合わせて、ポーリングロジックでソフトアサーションを実行できます。

const softExpect = expect.configure({ soft: true });
await softExpect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}, {}).toBe(200);

これにより、ポーリング内のアサーションが失敗してもテストが続行されます。

expect.toPass

コードのブロックが正常に通過するまで再試行できます。

await expect(async () => {
const response = await page.request.get('https://api.example.com');
expect(response.status()).toBe(200);
}).toPass();

カスタムのタイムアウトと再試行間隔も指定できます。

await expect(async () => {
const response = await page.request.get('https://api.example.com');
expect(response.status()).toBe(200);
}).toPass({
// Probe, wait 1s, probe, wait 2s, probe, wait 10s, probe, wait 10s, probe
// ... Defaults to [100, 250, 500, 1000].
intervals: [1_000, 2_000, 10_000],
timeout: 60_000
});

デフォルトでは、toPass のタイムアウトは 0 であり、カスタムのexpect timeoutは尊重されません。

expect.extend を使用したカスタムマッチャーの追加

カスタムマッチャーを提供することで、Playwright のアサーションを拡張できます。これらのマッチャーは expect オブジェクトで使用できます。

この例では、カスタムの toHaveAmount 関数を追加しています。カスタムマッチャーは、アサーションが成功したかどうかを示す pass フラグと、アサーションが失敗したときに使用される message コールバックを返す必要があります。

fixtures.ts
import { expect as baseExpect } from '@playwright/test';
import type { Locator } from '@playwright/test';

export { test } from '@playwright/test';

export const expect = baseExpect.extend({
async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
const assertionName = 'toHaveAmount';
let pass: boolean;
let matcherResult: any;
try {
const expectation = this.isNot ? baseExpect(locator).not : baseExpect(locator);
await expectation.toHaveAttribute('data-amount', String(expected), options);
pass = true;
} catch (e: any) {
matcherResult = e.matcherResult;
pass = false;
}

if (this.isNot) {
pass =!pass;
}

const message = pass
? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
'\n\n' +
`Locator: ${locator}\n` +
`Expected: not ${this.utils.printExpected(expected)}\n` +
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '')
: () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
'\n\n' +
`Locator: ${locator}\n` +
`Expected: ${this.utils.printExpected(expected)}\n` +
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '');

return {
message,
pass,
name: assertionName,
expected,
actual: matcherResult?.actual,
};
},
});

これで、テストで toHaveAmount を使用できます。

example.spec.ts
import { test, expect } from './fixtures';

test('amount', async () => {
await expect(page.locator('.cart')).toHaveAmount(4);
});

expect ライブラリとの互換性

Playwright の expectexpect ライブラリと混同しないでください。後者は Playwright テストランナーと完全に統合されていないため、Playwright 独自の expect を使用するようにしてください。

複数のモジュールからのカスタムマッチャーの結合

複数のファイルまたはモジュールからカスタムマッチャーを結合できます。

fixtures.ts
import { mergeTests, mergeExpects } from '@playwright/test';
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';

export const expect = mergeExpects(dbExpect, a11yExpect);
export const test = mergeTests(dbTest, a11yTest);
test.spec.ts
import { test, expect } from './fixtures';

test('passes', async ({ database }) => {
await expect(database).toHaveDatabaseUser('admin');
});