【Playwright】expect.softで一つのexpectが失敗した後もテストを続行させる(Soft Assertion)
はじめに
Playwrightでは、一つのテストの中に複数のassertion(expect)が存在する時、assertionが一つ失敗した時点でテストは失敗となり、後続は実行されません。
多くの場合はこれで困らないのですが、ビジュアルリグレッションテストを横断的にしたい時、たとえば本番環境と開発環境の複数のページを遷移して、それぞれのページのスクリーンショットを比較したい場合など、いちいち最初のエラーで止まってしまうと面倒です。最後にエラーをまとめて捕捉したい...
expectが失敗してもテストを止めずそのまま続行させたい時に使えるのが、expect.soft
です。
expect.soft
expect.soft
は以下のような挙動をします。
- assertionが失敗してもテストを続行する
- 一つでも失敗したassertionがあれば、テスト全体は失敗になる
- 失敗したassertionは
test.info().errors
から参照できる
実際の例を見てみます。
環境
- MacBook Air (M1, 2020)
- pnpm: 8.7.5
- playwright: 1.37.1
サンプルコード
通常のexpect
まず、通常のexpectの場合。
import { test, expect } from '@playwright/test';
test('assertionが失敗した時点で後続の処理はおこなわれない。', () => {
expect(2 + 2).toBe(5);
console.log('この行は実行されない。');
expect(42).toBeTruthy()
});
これを実行すると、最初のexpectで実行が止まり、2番目のexpectは実行されません。
2つ目のexpectは実行されない
expect.soft
を用いたSoft Assert
続いて以下はどうでしょうか。test.info().errors
も試してみます。
test('expect.softを使うと、assetionが失敗しても後続の処理がおこなわれる', () => {
// false
expect.soft(2 + 2).toBe(5);
console.log('この行は実行される。')
// true
expect.soft(42).toBeTruthy()
// false
expect.soft("Big Brother is watching you").toBeFalsy()
// 失敗したテストの数はtest.info().errorsで取得できる
// true
expect(test.info().errors.length).toBe(2);
});
実行すると下記の結果が得られます。
テストはfailとなり、失敗したexpectの内容が一覧で表示されます。
Test Stepsを見ると、それ以外のassertionは通っていることがわかります。
Test Stepsは最後のexpectまで結果が確認できる
expect.soft
の対応
おまけ:Jest / VitestのPlaywrightで使えるならJestでも使えるかと思いきや、そうでもなかったので、補遺です。
Jest: 使えない
Jestでは2023年9月12日現在、まだ実装されていないようです。
Feature RequestのIssueが立っていました。
Jestではexpect
がグローバルで、特定のテストで挙動を変えるのが難しい、とのこと。
Jestでは使えない
Vitest: 使える
一方でVitestでは使えます。
Feature Request。
It also should be easier to implement than in Jest, because our expect is bound to a test.
とあるように、Vitestの場合はexpect
が特定のテストにbindされているので実装ができたようです。違いがあるのですね。
Vitestによるサンプルコードも置いておきます。失敗したassertionはtask
から取り出すことができました。
test("expect.softを使うと、assetionが失敗しても後続の処理がおこなわれる", ({ task }) => {
// false
expect.soft(2 + 2).toBe(5)
console.log("この行は実行される。")
// true
expect.soft(42).toBeTruthy()
// false
expect.soft("Big Brother is watching you").toBeFalsy()
// 失敗したassertionはtaskから取得できる
// true
expect(task.result?.errors?.length).toBe(2)
})
おわりに
ということで、expect.soft
の簡単な紹介でした。
expect
の厳しさに耐えられなくなった時、失敗に寛容なexpect.soft
のやさしさを思い出してください。
サンプルコードは以下のGitHubに置いておきます。
テストの実行にはVSCodeの各フレームワークのテストランナーを用いました。
Discussion