こちらはNewsPicksアドベントカレンダー2022の6日目の記事です。
はじめに
業務でPlaywrightを用いたE2E自動テストを実装するタスクをしていて、ハマった場所があったため備忘録も兼ねて記事にしてみました。
Playwrightとは?
PlaywrightとはE2Eテストを自動化するNode.jsのフレームワークです。
ハマったこと
元々、
1つのテストファイル内で実行をする際にtest.beforeAll()を一回動作させ、test.beforeEach()でそれぞれのテストの事前処理を実行して欲しかったのですが、
並列実行で試してみたところ、
test.beforeAll()
がそれぞれ毎回呼ばれてしまったことがありました。
test.beforeAll()
, test.beforeEach()
について認識が浅かったために予想通りに動いてくれませんでした。
ドキュメントの解説はこちらです。
解説
test.beforeAll()
はテスト実行前にworker1つごとに一回ずつ実行されます。
そのため、例えば、
1つのファイル内で3つのテストを並列実行しようとすると、合計するとworkerが3つ走るため、test.beforeAll()
も結果それぞれのworker(テスト)に対して実行されます。
結論としては、1つのファイル内でテストを並列実行する際にtest.beforeAll()
を一回だけ走らせるといったことはできません。
test.beforeAll()
を一回だけ走らせたい場合は並列実行ではなく、順次実行でテストを実行させる必要があります。
補足
本記事は事前処理に使われるbeforeAll()
、beforeEach()
について紹介していますが、事後処理に使われる
afterAll()
afterEach()
についても同じことが言えるため事後処理などで困っている方も同じ様に置き換えて考えていただければと思います。
詳しく解説します
テストの事前処理について
test.beforeAll()
とtest.afterAll()
はどちらもtest()
が実行される前に実行されるもので、テストに必要な事前処理などを行うために使います。
例えば、
- ユーザ画面が表示されるかどうかをテストしたい
こういった時、事前にログインをする必要がある際にtest.beforeAll()やtest.beforeEach()内にログイン処理を書くことが多いです。
test.beforeAll()
とtest.beforeEach()
の違い
test.beforeAll()
とtest.beforeEach()
を使いこなす必要が出てくるのは、1つのテストファイル内に複数のtest()
が必要となってきた時です。
例えば、
test.beforeAll(async () => {
console.log('beforeAll')
})
test.beforeEach(async () => {
console.log('beforeEach')
})
// 1つのファイル内にtest()を2つ書く
test('hogehoge1', async () => {
console.log('テスト1')
})
test('hogehoge2', async () => {
console.log('テスト2')
})
test.afterEach(async () => {
console.log('afterEach')
})
test.afterAll(async () => {
console.log('afterAll')
})
これを実行すると、
beforeAll
beforeEach
テスト1
afterEach
beforeEach
テスト2
afterEach
afterAll
この様に表示されます。期待通りですよね。
playwrightはデフォルト設定では、1つのファイル内は順次実行の設定のため、実際に走るworkerの数としては1つとなるため期待通りの挙動をします。
しかし、
test.beforeAll(async () => {
console.log('beforeAll')
})
test.beforeEach(async () => {
console.log('beforeEach')
})
+ test.describe.configure({ mode: 'parallel' })
// 1つのファイル内にtest()を2つ書く
test('hogehoge1', async () => {
console.log('テスト1')
})
test('hogehoge2', async () => {
console.log('テスト2')
})
test.afterEach(async () => {
console.log('afterEach')
})
test.afterAll(async () => {
console.log('afterAll')
})
上記のファイルに
test.describe.configure({ mode: 'parallel' })
を追加して並列実行してみると、、
beforeAll
beforeEach
テスト1
afterEach
afterAll
beforeAll
beforeEach
テスト2
afterEach
afterAll
この様にbeforeAllが毎回呼ばれてしまいます。
理由としては、並列実行した際は複数のテストに対して複数のworkerプロセスが動くためです。
こちらに軽く説明があるのでご覧いただければと思います。
結論
1つのファイル内でbeforeAll()
を1回だけ実行したい場合は
並列実行ではなく、順次実行で実行する様にしましょう。
参考文献