DockerとCodeceptJSでどこでもE2E自動テスト

こんにちは、SMOOSYで試験を担当している鈴木です。
SMOOSYは、「宛名ラベル作成機能」「学会ウェブサイト作成機能」など新機能追加や、ユーザビリティテストによる改善など、ご利用いただく学協会の方に1つでも多くのValueを届けられるようにどんどんブラッシュアップしています。
そしてそれに欠かせないのが品質を保証するテストですが、新機能や改善箇所だけでなく、既存の機能も問題なく動作するかを確認していく必要があります。
ただ、機能が増えれば増えるだけテストパターンも増えていく訳で、効率的にテストしていくために避けて通れないのが自動化です。
ということで、今回はテスト自動化の中でE2E(End to End)テストに関するフレームワーク「CodeceptJS」についてご紹介します。

CodeceptJSって何?

Node.jsで動作するJavaScriptで作成されたテストフレームワークです。
CodeceptJSは、WebDriver、Puppeteerといったテストドライバーを使って、各種ブラウザの操作やテストができます。

CodeceptJSのアーキテクチャ

なぜCodeceptJS

E2Eテストの自動化を検討している時、最初はSeleniumやKatalon Studioなどレコーディング機能をもつGUIテストフレームワークを使っていろいろ試していました。
そこでいつも課題となるのが、メンテナンスのしやすさでした。
レコーディング機能で操作を記憶させた場合、XPathで記録されるので画面構成が少しでも変わるとテストコードの修正が必要となり、とてもメンテナンスに手間がかかります。
その対策としてテストコード上で#IDなどのCSSセレクタに書き換える作業が必要となるため、レコーディング機能の有効性はあまり無いなと思うようになりました。
また、CI環境での利用を考えるとGUIを持つ必要もなく、以下のような観点でテストフレームワークを探してCodeceptJSに行き着きました。

  1. テストコードが簡単に書ける
  2. テスト結果が見やすい
  3. クロスブラウザ環境のテストができる
  4. 環境構築が簡単

CodeceptJSの特徴

1. テストコードが簡単に書ける

HTML要素の構成を把握していなくてもセレクタが書ける

以下のような「会員管理支援サービス」というリンクをクリックする場合、

セレクタの例

WebDriver(JavaScript)では次のようにセレクタをXPathで書けますが、HTML要素の構成を把握しておく必要があります。

CodeceptJSでは次のようにHTML要素の構成を把握せずにセレクタが書けます。

これはCodeceptJSが提供している Semantic Locator によるもので、以下のようにアクション対象の画面項目を検索します。

  • クリックclick() の場合:指定されたテキストを持つリンクやボタン(<a><click><input type="submit">など)を検索
  • フィールド入力fillField()の場合:指定されたテキストをラベルやプレースホルダー、nameに含む入力項目(<input><textarea>など)を検索

なお、次のようにCSSセレクタやXPathを指定することもできます。

直感的にわかりやすいテストコード

例えば表示内容を検証したい場合、WebDriver(JavaScript)では次のように2ステップを書く必要があります。

CodeceptJSでは次のように1ステップで書くことができ、テスト手順と対応したシンプルなテストコードにできます。

なお、利用できるメソッドはWebDriver、Puppeteer、Nightmareなど、テストドライバーによって若干異なりますが、主要なメソッドは共通で使えます。
詳細については、以下の公式ドキュメントをご覧ください。

画面の切り替わりなどアクション待ちを意識しなくて良い

テスト対象のサイトがSPAやAjaxを利用している場合、画面の切り替わりが終わらないうちに次のアクションが実行されてエラーとなることがあります。
その対策のため、画面の切り替わりを待つためのコードを追加する必要がありますが、テストコードを書く上では意外と手間になります。
CodeceptJSではアクションが失敗した場合に自動でリトライする RetryFailedStep プラグインがあり、これを有効にすることでアクション待ちのコードを明示的に書く必要がなくなります。
プラグインは、次のように設定ファイルに追記するだけで有効となります。

なお、デフォルトでは1,000ms(1秒)間隔で最大5回リトライします。

対話型でステップ毎にテストコードを試せる

次のようにshellオプションを指定してCodeceptJSを実行すると、対話型で1ステップずつ試しながらテストコードが書けます。

I.というプロンプトが表示されるので、amOnPage('https://www.atlas.jp');などテストコードを入力してEnterすると実行されます。

実行が失敗した場合は、「FAIL」「ERROR」といったキーワードと共にエラーメッセージが表示されます。
最初のアクションからやり直さなくても、エラーとなったテストコードを入力し直して再度実行できます。
また、TABキーでメソッドの補完や、カーソルキーで過去に実行した履歴を表示できます。
なお、exitを入力してEnterすると対話型モードが終了します。

デバッグのためのコンソール出力が不要で、テストコードファイルを修正して最初からテストをやり直さなくても良いため、セレクタが正しく認識してくれるかなどを試す時はとても便利です。

2. テスト結果が見やすい

ステップ毎にスクリーンショットが取得できる

テスト結果のエビデンスとしてスクリーンショットを取得したいということは良くあると思いますが、CodeceptJSでは StepByStepReport プラグインを有効にすることでステップ毎に自動でスクリーンショットを取得してくれます。
プラグインは、次のように設定ファイルに追記するだけで有効となります。

プラグインを有効にしてテストを実行すると、スクリーンショットをスライドショー形式にしたHTMLが生成され、パスが次のように表示されます。

表示されたHTMLパスへアクセスすると以下のようなスクリーンショットレポートを参照できます。

StepByStepレポート

レポートツールと連携できる

allure プラグインを有効にすることで、CodeceptJSのテスト結果を Allureレポートツール で閲覧できるようになります。
プラグインは、次のように設定ファイルに追記するだけで有効となります。

プラグインを有効にしてテストを実行すると、「output」ディレクトリ以下にレポートデータ用のXMLが保存されます。
Allureでレポートを参照するには、次のようにAllureレポートツールをインストールします(※AllureはJavaで動作するため、事前にJava8以上のインストールが必要です)。

インストール後、次のようにレポートデータが保存されているディレクトリを指定して、Allureを起動します。

Allureが起動するとブラウザが自動起動して以下のようなレポートが確認できます。

Allreレポートツール

3. クロスブラウザ環境のテストができる

CodeceptJSはNode.jsが動作する環境であれば、Mac/Windows/CI環境(Linux)とどこでも実行できます。
また、WebDriverIO、Puppeteer、Nightmareなどテストドライバーを設定ファイルで切り替えることで、各種ブラウザのクロスブラウザテストができます。

4. 環境構築が簡単

CodeceptJSは、npmで本体と使用するテストドライバーをインストールすることで利用できます。

また、DockerHubで各種テストドライバーを含めた公式コンテナイメージが公開されており、Docker環境があればすぐにテストが実行できます。

Docker環境でどこでもE2E自動テスト

それでは、実際にDocker環境でCodeceptJSを実行してみましょう。
例では、CI環境などブラウザがインストールされていない環境での実行を考慮して、Nightmareテストドライバーを使用しています。

テスト用ディレクトリの準備

Dockerコンテナにマウントするテスト用ディレクトリを作成し、CodeceptJSの設定ファイル、テストコードファイルを用意します。

テスト実行

テスト用ディレクトリに移動して、docker runコマンドで実行します。

以上のように簡単にテストができますので、E2Eテストの自動化を検討されている方は是非お試しください。

おわりに

CodeceptJSはシンプルなテストコードのため、様々なツールと組み合わせて利用できます。
例えば、Googleスプレッドシートで、画面URL、画面項目のCSSセレクタID、アクション、確認内容をまとめれば、テストコードの自動生成も容易にできます。
また、Appiumテストドライバーによるモバイルアプリのテスト、RESTヘルパーによるREST APIのテスト、画像比較によるビジュアルテストなど、様々なプラグインが用意されており、幅広い活用が期待できます。
今後もSMOOSYのブラッシュアップに合わせて、自動テスト環境も拡充していきますので、またの機会に紹介できたらと思います。