cordovaアプリをCircleCI上でe2eテストする
こんにちは.cordovaデビューした maxmellon です
今回は,cordova で作られたアプリケーションを CircleCI 上 でe2eテストする方法について触れたいと思います
はじめに
この記事の関連ワード
継続的インテグレーション, CIとは : 継続的インテグレーションとは|CI|Continuous Integration - 意味/定義 : IT用語辞典
CircleCI とは : CIサービスの一種,Githubと連携し push されたことを検出しテストを走らせるものがほとんど.ほかにも travisCI などが挙がる
cordova とは : HTML5ハイブリッドアプリ開発を支えるOSS「Cordova」はなぜアツいのか?PhoneGapとの違いは何か? - ふろしき.js
e2eテスト とは : システム全体が正しく動作することを確認するためのテスト.(e2eは end to end の略)
上記の内容を把握していると, より記事の内容がわかりやすいと思います.
e2eラッパにー nightmare をつかう
end to end テストは,nightmare を使わなくてもそのまま phantomjs
と アサーションライブラリを用いれば書くことができるが,なかなかに記述量が多くなりめんどくさい.
また,ドライバーに phantomjs
を使うと,Symbol などのモダンなAPIが利用できない.
そこで,nightmare
を使う.
nightmare
は version2 から,ドライバーが ※1 electron
になり,OSなどの環境の違いを意識することなく,e2eテストを書くための環境を提供してくれる.
※1 Electronとは、Node.jsとChromiumをベースとしたデスクトップアプリケーションを作成するクロスプラットフォーム実行環境です。
人々はもう phantomjs
のバージョンに悩まなくて済むのだ
(2.0.0 以前は ※2 bind() がないため React が動かない,2.0.0 < 2.1.0 は ※3 ファイルアップロードがうまく動かない.など)
※2 Circleci上でPhantomjsを使ってReactアプリをテストする
※3 Webpage.uploadFile not working in phantomjs 2.0
electron であればこういったことに悩まなくて済む.
ついでに,selenium diriver
みたいに重くもないし起動もそこそこ速いというメリットも得られる.
テストの書きやすさ比較
これは,公式ページにある例が非常にわかりやすいので,引用して載せておく.
cordova アプリケーションを nightmare で e2e テストする
テストの書き方
テストは次のように書くことができます.
var Nightmare = require('nightmare'); var nightmare = Nightmare({ show: true }) nightmare .goto('http://yahoo.com') .type('form[action*="/search"] [name=p]', 'github nightmare') .click('form[action*="/search"] [type=submit]') .wait('#main') .evaluate(function () { return document.querySelector('#main .searchCenterMiddle li a').href }) .end() .then(function (result) { console.log(result) }) .catch(function (error) { console.error('Search failed:', error); });
これをavaを使って書くと,
import test from 'ava'; import Nightmare from 'nightmare'; const nightmare = Nightmare({ show: true }); test.serial('Generators!', function * (t) { const result = yield nightmare .goto('http://yahoo.com') .type('form[action*="/search"] [name=p]', 'github nightmare') .click('form[action*="/search"] [type=submit]') .wait('#main') .evaluate(() => document.querySelector('#main .searchCenterMiddle li a').href); t.true(result.includes('images.search.yahoo.com')); }); test.serial('Async/Await!', async t => { const result = await nightmare .goto('http://yahoo.com') .type('form[action*="/search"] [name=p]', 'github nightmare') .click('form[action*="/search"] [type=submit]') .wait('#main') .evaluate(() => document.querySelector('#main .searchCenterMiddle li a').href); t.true(result.includes('images.search.yahoo.com')); });
このように書くことができます.
Generator, async/await を使うことにより,非同期でエミュレートされているものの終了を待っています.
詳しいテストを書くためのAPIは,https://github.com/segmentio/nightmare#api を参照してください.
大体は, evaluate で 実DOM を 返して,そのDOMの状態が期待した状態かをチェックしていく感じです.
テストを実行するための環境を構築する
cordova は グローバルにインストールされているとして話を進めていきます.
node
>= 6.2.0npm
>= 3.9.5
$ npm install --save-dev ava nightmare
テストを実行するためのスクリプトを作成する
$ mkdir e2e $ touch e2e/test.js # 任意のエディタで e2e/test.js を開く
import test from 'ava'; import Nightmare from 'nightmare'; const nightmare = Nightmare({ // CI上ではない時は,dev tool と window を表示 show: process.env.CI !== 'true', openDevTools: { detach: process.env.CI !== 'true' }, }); // これより下に,テストケースを追加していく // Example test.serial('Generators!', function * (t) { const result = yield nightmare .goto('http://yahoo.com') .type('form[action*="/search"] [name=p]', 'github nightmare') .click('form[action*="/search"] [type=submit]') .wait('#main') .evaluate(() => document.querySelector('#main .searchCenterMiddle li a').href); t.true(result.includes('images.search.yahoo.com')); });
package.json を 次のように編集
"scripts": { "build:browser": "cordova build browser", "browser": "npm run build:browser && cordova run browser", "pree2e": "npm run browser &", "e2e": "wait-on http://localhost:8000 && ava --verbose e2e/test.js", },
これで,テストを実行する環境は整いました.
npm run e2e
をコマンドラインで実行することでテストが走ります.
CircleCI上で動作させる
CricleCI上で動かすために,特別にすることがありません.
ただ,background で 走らせたサーバーを落とさないかぎり CI も終わらないので,サーバーを落とすタスクを追加します
cirlce.yml を次のように編集します
machine: node: version: 6.2.0 dependencies: override: - "npm install" - "npm install -g cordova" post: - "cordova platform add browser" test: override: - "npm run e2e" - "kill -9 `ps | grep -v grep | grep cordova/run | awk -F ' ' '{print }'` >/dev/null 2>&1 || exit 0"
テスト実行前にplatformを追加しています. テストが終わったあとに,サーバーのプロセスをkillしています.
こうすることで,nightmareによる e2e テストをCircleCI上で実行することができます.
余談
CircleCI では, Xvfd (仮想 X デーモン) がデフォルトで起動しています. なので,特に設定しなくても electron を実行することができました.
TravisCIの場合は,Xvfd をインストールして,起動して DISPLAY環境変数を export することで, 同様に,electron を実行することができます.
詳しくは,こちらを御覧ください
https://github.com/electron/electron/blob/master/docs/tutorial/testing-on-headless-ci.md
まとめ
- Phantomjs から 脱却することで高速に e2e テストすることができる.
- CircleCI 上でも e2e テストを実行することができる.
- electron なので, 開発者のPCのOSに依存することがない.