Javascript 製のE2Eテスト(puppeteer)に纏わるちょっとした工夫
この記事は、ソフトウェアテストの小ネタ Qiita Advent Calendar 2019 の24日目の記事です。 puppeteer を触っているときにちょっとした工夫を2つほど思いついたので、コード例と共に記事にしようと思います。
テスト部分を try ~ catch ~ finally で括ると、テストに落ちた時や終了した時の処理をカスタマイズできる
puppeteer は node 製のライブラリなので、javascript で使われている try ~ catch ~ finally句が使用できます。
テスト部分を try ~ catch ~ finally 句で括ると、catch 句ではテストに落ちた時の処理を、finally 句では終了した時の処理をカスタマイズできます。
コード例
import Puppeteer from 'puppeteer'; import test from 'ava'; test.serial('ログイン_成功', async (t) => { const browser = await Puppeteer.launch({ "ignoreHTTPSErrors" : true, }); const page = await browser.newPage(); try { await page.goto("https://hoge.com"); await page.type(".mail-address", "hoge@huga.jp"); await page.waitFor(500); await page.type('.password', "test"); await page.waitFor(500); await page.click('.login'); await page.waitFor('.logout'); const result = await page.evaluate(() => { return document.querySelector('.logout').innerHTML; }); t.true(result.includes('ログアウト')); } catch (e) { // テストに失敗したら、スクリーンショットを撮って保存する const todayDateTime = new Date(); const formatTodayDateTime = String(todayDateTime.getFullYear()) + String(todayDateTime.getMonth() + 1) + String(todayDateTime.getDate()) + String(todayDateTime.getHours()) + String(todayDateTime.getMinutes()); + String(todayDateTime.getSeconds()); await page.screenshot({ path: 'screenshot/' + formatTodayDateTime + '_error_login.png', fullPage: true }); t.fail('ログインテストに失敗しました。スクリーンショットをご確認ください。\nエラーメッセージ内容:' + e.message); } finally { // テストに成功しようが失敗しようがブラウザは閉じる await browser.close(); } });
私は上記のように、「失敗した時はスクリーンショットを取って保存する」「テスト終了した時は必ずブラウザを閉じる」処理を追加しています。
環境によって違う値は、定数ファイルに保存しておくと管理が楽
ログインIDやパスワードといった環境ごとに値が違う場合は、定数ファイルにまとめて保存すると管理が楽になります。 仮にテストデータのリセットが行われたとしても、1カ所直すだけですむためです。
私は configと呼ばれる、環境変数(env)によって定数の値を変えるライブラリを使っています。
コード例
test.js
import Puppeteer from 'puppeteer'; import test from 'ava'; test.serial('ログイン_成功', async (t) => { const browser = await Puppeteer.launch({ "ignoreHTTPSErrors" : true, }); const page = await browser.newPage(); await page.goto("https://hoge.com"); await page.type(".mail-address", config.get("front.user.mail") ); await page.waitFor(500); await page.type('.password', config.get("front.user.password")); await page.waitFor(500); await page.click('.login'); await page.waitFor('.logout'); const result = await page.evaluate(() => { return document.querySelector('.logout').innerHTML; }); t.true(result.includes('ログアウト')); await browser.close(); });
testing.json
{ "front": { "user": { "mail": "hoge@huga.jp", "password": "Test2" }, }
staging.json
{ "front": { "user": { "mail": "piyo@foo.jp", "password": "Test2" }, }
package.json
{ "name": "e2e-test", "version": "1.0.0", "description": "", "scripts": { "test_testing": "NODE_ENV=testing ava --verbose", "test_staging": "NODE_ENV=staging ava --verbose" }, "devDependencies": { "ava": "*", "config": "*", "puppeteer": "*" } }
テスト実行時に NODE_ENV という環境変数を使って、使用する定数ファイルを指定しています。