kkAyatakaのメモ帳。

誰かの役に立つかもしれない備忘録。

CodeceptJSを動かしてみる

Seleniumとテスティングフレームワークについて調べながらTweetしていたところ、CodeceptJSを薦められるってことがありまして。...ネタか?と思ったりもしたものの、思想的にも作り的にも面白く、今回テストの自動化にあたり、狙っている領域にうまくはまりそうだったので、動かしてみることにしました。

軽く動かすには、公式ページのQuickstartの「Using Selenium WebDriver」まんまでOK。

SleniumやJasmine + jQueryあたりでの自動化だと、UI要素の指定がネックになるなぁと感じていたところで、UI要素を大体で指定できる「Semantic Locators」がかなり良い感じ。出来上がるコードもUI操作が明確で普通に読みやすく、使いやすそうです。

環境

  • Windows 10 1809
  • Google Chrome 76.0.3809.100(Official Build) (64 ビット)
  • Node.js v10.16.2
  • Java OpenJDK 11 64-bit (11+28)
  • ChromeDriver(単独で動かした場合)
    • Node.jsのselenium-standaloneを使用する場合は不要だけど、単独で動かす場合に必要
    • ChromeDriver 76.0.3809.68
    • Selenium Standalone Server 3.141.59

セットアップ

  • 作業用に適当にフォルダを準備(hello-codeceptjs)して、とりあえずnpm init
  • npm install codeceptjs webdriverioでCodeceptJSとWebDriverIOをインストール
  • ChromeDriverの実行方法を選んで準備する
    • npm install @wdio/selenium-standalone-serviceを実行して@wdio/selenium-standalone-serviceを使用する
      • 自動的にChromeDriver(Selenium Standalone Server)が実行される
      • ただ、テストが終了してもChromeDriverプロセスが終了しない...(v5.12.1)
    • npm instaell selenium-standaloneを実行してselenium-standaloneを直接使う
      • npx selenium-standalone installを実行してドライバー類のダウンロードが必要
      • テスト実行前にnpx selenium-standalone startを実行して、あらかじめselenium-standaloneを動かしておく
      • 実動作は@wdio/selenium-standalone-serviceと同じだけど、こちらはChromeDribverがテスト実行後にちゃんと終了する
    • Selenium Standalone Serverをダウンロードして実行する
      • 事前にChromeDriverをダウンロードして、パスが通っているところに置く/パスを通す
        • e.g. C:\Users\kkAyataka\.local\.bin
      • java -jar selenium-server-standalone-3.141.59.jar
  • npm install -g lite-serverで簡易のWebサーバーを用意する

初期化

CodeceptJSは各種ジェネレーター用のコマンドがそろっていて、コードのひな型を生成してくれる。初期化はnpx codeceptjs initで、設定用JS等が自動的に生成される。

途中でWebDriverchromeを選ぶ。デフォルトで日本語(ja-JP)もある。

$ npx codeceptjs init

  Welcome to CodeceptJS initialization tool
  It will prepare and configure a test environment for you

Installing to D:\Projects\hello-world\hello-codeceptjs
? Where are your tests located? ./*_test.js
? What helpers do you want to use? WebDriver
? Where should logs, screenshots, and reports to be stored? ./output
? Would you like to extend the "I" object with custom steps? Yes
? Where would you like to place custom steps? ./steps_file.js
? Do you want to choose localization for tests? ja-JP
Configure helpers...
? [WebDriver] Base url of site to be tested http://localhost
? [WebDriver] Browser in which testing will be performed chrome

npx codeceptjs gtで空のテストを作成する。ファイル名の「_test」は自動で付く。 出来上がるコードがシンプルなので、使用する必要性は感じないけど、現状では不要かまでは判断つかない。

$ npx codeceptjs gt

Creating a new test...
----------------------
? Filename of the test index
? Feature which is being tested Index

テスト用HTML

操作対象のHTMLは前回と同じものを使う。 #buttonをクリックすると#stageのテキストが変わるというもの。 CodeceptJSで#buttonをクリックし、#stageの内容をチェックする。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <script>
    function onLoad() {
      const btn = document.getElementById('button');
      const stage = document.getElementById('stage');

      // #buttonで#stageの内容を書き換える
      btn.addEventListener('click', (e) => {
        stage.innerHTML = 'Hello';
      });
    }
  </script>
  <body onload="onLoad()">
    <h1>Hello, World</h1>
    <button type="button" id="button">Button</button>
    <div id="stage" >Initial</div>
  </body>
</html>

index_test.js

I.seeアサーション。かなりアバウトに書けて、「Initial」という文字列がHTML内にあるかどうかで判定しているっぽい。 確かに多くのケースはこれでカバーできそうで、割り切りがうまい。

ボタンの判定もSemantic Locatorと言って、 厳密に指定しなくてもイイ感じに見つけて動作する。 全てのケースをカバーできるわけでは無いけど、自動化の際UIコンポーネントの指定の煩雑さ/難しさは課題になるので、この考え方は面白い。

Feature('Index test');

Scenario('test stage text', (I) => {
  I.amOnPage('http://localhost:3000');
  I.see('Initial');
  I.click('button');
  I.see('Hello');
});

実行

とりあえず、lite-serverを動かして...

$ lite-server .

selenium-standaloneも動かす。

$ npx selenium-standalone start

で、テスト実行。日本語に設定していると日本語で出力される。簡単な翻訳なんだけどだいぶ読みやすい。

$ npx codeceptjs run --steps
CodeceptJS v2.3.0
Using test root "D:\Projects\hello-world\hello-codeceptjs"

Index test --
  test stage text
    私は ページを移動する "http://localhost:3000"
    私は テキストがあるか確認する "Initial"
    私は クリックする "button"
    私は テキストがあるか確認する "Hello"
  √ OK in 466ms

参考