2019/12/24
DockerとCodeceptJSでどこでもE2E自動テスト
目次
こんにちは、SMOOSYで試験を担当している鈴木です。
SMOOSYは、「宛名ラベル作成機能」「学会ウェブサイト作成機能」など新機能追加や、ユーザビリティテストによる改善など、ご利用いただく学協会の方に1つでも多くのValueを届けられるようにどんどんブラッシュアップしています。
そしてそれに欠かせないのが品質を保証するテストですが、新機能や改善箇所だけでなく、既存の機能も問題なく動作するかを確認していく必要があります。
ただ、機能が増えれば増えるだけテストパターンも増えていく訳で、効率的にテストしていくために避けて通れないのが自動化です。
ということで、今回はテスト自動化の中でE2E(End to End)テストに関するフレームワーク「CodeceptJS」についてご紹介します。
CodeceptJSって何?
Node.jsで動作するJavaScriptで作成されたテストフレームワークです。
CodeceptJSは、WebDriver、Puppeteerといったテストドライバーを使って、各種ブラウザの操作やテストができます。
なぜCodeceptJS
E2Eテストの自動化を検討している時、最初はSeleniumやKatalon Studioなどレコーディング機能をもつGUIテストフレームワークを使っていろいろ試していました。
そこでいつも課題となるのが、メンテナンスのしやすさでした。
レコーディング機能で操作を記憶させた場合、XPathで記録されるので画面構成が少しでも変わるとテストコードの修正が必要となり、とてもメンテナンスに手間がかかります。
その対策としてテストコード上で#IDなどのCSSセレクタに書き換える作業が必要となるため、レコーディング機能の有効性はあまり無いなと思うようになりました。
また、CI環境での利用を考えるとGUIを持つ必要もなく、以下のような観点でテストフレームワークを探してCodeceptJSに行き着きました。
- テストコードが簡単に書ける
- テスト結果が見やすい
- クロスブラウザ環境のテストができる
- 環境構築が簡単
CodeceptJSの特徴
1. テストコードが簡単に書ける
HTML要素の構成を把握していなくてもセレクタが書ける
以下のような「会員管理支援サービス」というリンクをクリックする場合、
WebDriver(JavaScript)では次のようにセレクタをXPathで書けますが、HTML要素の構成を把握しておく必要があります。
1 2 |
// 「会員管理支援サービス」をテキストに持つspanを子要素に持つリンクをクリック $('//a[child::span[text()=\"会員管理支援サービス\"]]').click() |
CodeceptJSでは次のようにHTML要素の構成を把握せずにセレクタが書けます。
1 |
I.click('会員管理支援サービス'); // 「会員管理支援サービス」をクリック |
これはCodeceptJSが提供している Semantic Locator によるもので、以下のようにアクション対象の画面項目を検索します。
- クリック
click()
の場合:指定されたテキストを持つリンクやボタン(<a>
、<click>
、<input type="submit">
など)を検索 - フィールド入力
fillField()
の場合:指定されたテキストをラベルやプレースホルダー、nameに含む入力項目(<input>
、<textarea>
など)を検索
なお、次のようにCSSセレクタやXPathを指定することもできます。
1 2 |
I.click('#button'); I.click('//a[child::span[text()=\"会員管理支援サービス\"]]'); |
直感的にわかりやすいテストコード
例えば表示内容を検証したい場合、WebDriver(JavaScript)では次のように2ステップを書く必要があります。
1 2 |
const title = $('.page-titlearea').getText() // タイトルからテキストを取得 assert.strictEqual(title, '検索結果') // 取得したテキストが「検索結果」であること |
CodeceptJSでは次のように1ステップで書くことができ、テスト手順と対応したシンプルなテストコードにできます。
1 |
I.see('検索結果'); // 画面に「検索結果」が表示されていること |
なお、利用できるメソッドはWebDriver、Puppeteer、Nightmareなど、テストドライバーによって若干異なりますが、主要なメソッドは共通で使えます。
詳細については、以下の公式ドキュメントをご覧ください。
画面の切り替わりなどアクション待ちを意識しなくて良い
テスト対象のサイトがSPAやAjaxを利用している場合、画面の切り替わりが終わらないうちに次のアクションが実行されてエラーとなることがあります。
その対策のため、画面の切り替わりを待つためのコードを追加する必要がありますが、テストコードを書く上では意外と手間になります。
CodeceptJSではアクションが失敗した場合に自動でリトライする RetryFailedStep プラグインがあり、これを有効にすることでアクション待ちのコードを明示的に書く必要がなくなります。
プラグインは、次のように設定ファイルに追記するだけで有効となります。
1 2 3 4 5 |
plugins: { retryFailedStep: { enabled: true }, }, |
なお、デフォルトでは1,000ms(1秒)間隔で最大5回リトライします。
対話型でステップ毎にテストコードを試せる
次のようにshell
オプションを指定してCodeceptJSを実行すると、対話型で1ステップずつ試しながらテストコードが書けます。
1 2 3 4 5 6 7 8 9 |
$ npx codeceptjs shell String interactive shell for current suite... Interactive shell started Use JavaScript syntax to try steps in action - Press ENTER to run the next step - Press TAB twice to see all available commands - Type exit + Enter to exit the interactive shell I. |
I.
というプロンプトが表示されるので、amOnPage('https://www.atlas.jp');
などテストコードを入力してEnterすると実行されます。
1 |
I.amOnPage('https://www.atlas.jp'); |
実行が失敗した場合は、「FAIL」「ERROR」といったキーワードと共にエラーメッセージが表示されます。
最初のアクションからやり直さなくても、エラーとなったテストコードを入力し直して再度実行できます。
また、TABキーでメソッドの補完や、カーソルキーで過去に実行した履歴を表示できます。
なお、exit
を入力してEnterすると対話型モードが終了します。
1 2 3 4 5 6 7 8 9 |
I.amOnPage('https://www.atlas.jp'); I.fillField('s','smoosy'); I.click('button'); I.seeElement({ xpath: '//a[parent::span[text()=\"会員管理支援サービス\"]]' }); FAIL expected number of elements on a page "0" not to equal "0" I.seeElement({ xpath: '//a[child::span[text()=\"会員管理支援サービス\"]]' }); I.click({ xpath: '//a[child::span[text()=\"会員管理支援サービス\"]]' }); I.exit Exiting interactive shell.... |
デバッグのためのコンソール出力が不要で、テストコードファイルを修正して最初からテストをやり直さなくても良いため、セレクタが正しく認識してくれるかなどを試す時はとても便利です。
2. テスト結果が見やすい
ステップ毎にスクリーンショットが取得できる
テスト結果のエビデンスとしてスクリーンショットを取得したいということは良くあると思いますが、CodeceptJSでは StepByStepReport プラグインを有効にすることでステップ毎に自動でスクリーンショットを取得してくれます。
プラグインは、次のように設定ファイルに追記するだけで有効となります。
1 2 3 4 5 6 7 |
plugins: { stepByStepReport: { enabled: true, // step毎のスクリーンショットを取得する deleteSuccessful: false, // テスト成功時もスクリーンショットを残す fullPageScreenshots: true, // スクリーンショットはフルスクリーンで取得する }, }, |
プラグインを有効にしてテストを実行すると、スクリーンショットをスライドショー形式にしたHTMLが生成され、パスが次のように表示されます。
1 |
◉ Step-by-step preview: file:///tests/output/records.html |
表示されたHTMLパスへアクセスすると以下のようなスクリーンショットレポートを参照できます。
レポートツールと連携できる
allure プラグインを有効にすることで、CodeceptJSのテスト結果を Allureレポートツール で閲覧できるようになります。
プラグインは、次のように設定ファイルに追記するだけで有効となります。
1 2 3 4 5 |
plugins: { allure: { enabled: true // allureレポート連携を有効にする }, }, |
プラグインを有効にしてテストを実行すると、「output」ディレクトリ以下にレポートデータ用のXMLが保存されます。
Allureでレポートを参照するには、次のようにAllureレポートツールをインストールします(※AllureはJavaで動作するため、事前にJava8以上のインストールが必要です)。
1 |
$ sudo npm install -g allure-commandline --save-dev |
インストール後、次のようにレポートデータが保存されているディレクトリを指定して、Allureを起動します。
1 2 3 4 5 6 7 |
$ allure serve output Generating report to temp directory... Report successfully generated to /var/folders/1b/x9my1nsd6wgd6b11mp4mr81h0000gn/T/6459748190223707630/allure-report Starting web server... 2019-11-21 15:33:42.182:INFO::main: Logging initialized @4269ms to org.eclipse.jetty.util.log.StdErrLog Server started at <http://127.0.0.1:62424/>. Press <Ctrl+C> to exit |
Allureが起動するとブラウザが自動起動して以下のようなレポートが確認できます。
3. クロスブラウザ環境のテストができる
CodeceptJSはNode.jsが動作する環境であれば、Mac/Windows/CI環境(Linux)とどこでも実行できます。
また、WebDriverIO、Puppeteer、Nightmareなどテストドライバーを設定ファイルで切り替えることで、各種ブラウザのクロスブラウザテストができます。
4. 環境構築が簡単
CodeceptJSは、npmで本体と使用するテストドライバーをインストールすることで利用できます。
1 2 3 4 5 6 |
$ mkdir e2e_test && cd e2e_test $ npm init $ npm install codeceptjs nightmare puppeteer $ npx codeceptjs init |
また、DockerHubで各種テストドライバーを含めた公式コンテナイメージが公開されており、Docker環境があればすぐにテストが実行できます。
Docker環境でどこでもE2E自動テスト
それでは、実際にDocker環境でCodeceptJSを実行してみましょう。
例では、CI環境などブラウザがインストールされていない環境での実行を考慮して、Nightmareテストドライバーを使用しています。
テスト用ディレクトリの準備
Dockerコンテナにマウントするテスト用ディレクトリを作成し、CodeceptJSの設定ファイル、テストコードファイルを用意します。
1 2 3 |
e2e_test ├── codecept.conf.js ← 設定ファイル └── sample_test.js ← テストコードファイル(ファイル名の末尾は `_test.js`) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
exports.config = { tests: './*_test.js', //テストファイル名の最後は `_test.js` とする output: './output', // カレントディレクトリのoutputディレクトリ以下に試験結果を出力する helpers: { Nightmare: { // テストドライバーはNightmareを使用 } }, plugins: { allure: { enabled: true // allureレポート連携を有効にする }, stepByStepReport: { enabled: true, // step毎のスクリーンショットを取得する deleteSuccessful: false, // テスト成功時もスクリーンショットを残す fullPageScreenshots: true, // スクリーンショットはフルスクリーンで取得する }, retryFailedStep: { enabled: true // アクション失敗時は自動リトライする }, }, } |
1 2 3 4 5 6 7 8 9 10 11 |
Feature('サンプル試験') Scenario('検索試験', (I) => { I.amOnPage('https://www.atlas.jp'); // アトラスサイトにアクセス I.see('アトラスについて'); // 画面に「アトラスについて」が表示されていること I.fillField('s','smoosy'); // 検索欄に「smoosy」を入力 I.click('button'); // 検索ボタンをクリック I.see('検索結果'); // 画面に「検索結果」が表示されていること I.click('会員管理支援サービス'); // 「会員管理支援サービス」をクリック I.see('SMOOSY'); // 画面に「SMOOSY」が表示されていること }) |
テスト実行
テスト用ディレクトリに移動して、docker runコマンドで実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
$ cd e2e_test $ docker run --net=host -v $PWD:/tests codeception/codeceptjs codeceptjs run --steps Unable to find image 'codeception/codeceptjs:latest' locally latest: Pulling from codeception/codeceptjs 092586df9206: Pull complete ef599477fae0: Pull complete 4530c6472b5d: Pull complete d34d61487075: Pull complete 87fc2710b63f: Pull complete e83c771c5387: Pull complete c28bd271641e: Pull complete 5137e6957710: Pull complete 1d8bcbc41a69: Pull complete 6b5bc764a7a9: Pull complete 6819021fb65a: Pull complete 278cba7ef441: Pull complete 2e6624294749: Pull complete 9eb25b4a72ef: Pull complete 1e428b233139: Pull complete af9c5d08bc03: Pull complete 3506d86a5b49: Pull complete 01afa5a011eb: Pull complete Digest: sha256:bad4d56644c8bdc18b4c285c44cfbb46ab5dffaad942ec15f7d89efcf69c79ed Status: Downloaded newer image for codeception/codeceptjs:latest CodeceptJS v2.3.5 Using test root "/tests" サンプルテスト -- 検索テスト I am on page "https://www.atlas.jp" I see "アトラスについて" I fill field "s", "smoosy" I click "button" I see "検索結果" I click "会員管理支援サービス" I see "SMOOSY" ✔ OK in 8575ms OK | 1 passed // 9s ◉ Step-by-step preview: file:///tests/output/records.html |
以上のように簡単にテストができますので、E2Eテストの自動化を検討されている方は是非お試しください。
おわりに
CodeceptJSはシンプルなテストコードのため、様々なツールと組み合わせて利用できます。
例えば、Googleスプレッドシートで、画面URL、画面項目のCSSセレクタID、アクション、確認内容をまとめれば、テストコードの自動生成も容易にできます。
また、Appiumテストドライバーによるモバイルアプリのテスト、RESTヘルパーによるREST APIのテスト、画像比較によるビジュアルテストなど、様々なプラグインが用意されており、幅広い活用が期待できます。
今後もSMOOSYのブラッシュアップに合わせて、自動テスト環境も拡充していきますので、またの機会に紹介できたらと思います。