こんにちは、フロントエンドエンジニアのいなばです。
先日iPhone5からiPhone6sへ機種変更をしました。
サイズがでかいのは慣れませんが指紋認証すごいですね。
さて、今回はProtractorを使ってE2Eテストを実行できる環境をつくってみました。
Windowsをお使いの方は動かなかったらごめんなさい。
今回作ってみたE2Eテスト環境のリポジトリはこちらになります。
早速テストを書いてみましょう……の前に
すぐE2Eテストを書いてみたい方は、導入まで読み飛ばしてください。
E2Eテストとは
E2Eというのは、「End to End(エンドツーエンド)」の略で、「両端で」「端から端まで」という意味の言葉だそうです。
E2Eテストは、Webサイトやアプリケーションの「開始から終了まで」が、期待通り動いているかをテストします。
みなさん、Webサイトなどのリリース前には複数のブラウザや端末を操作して、目視で動作確認をしていますよね。今回はProtractorを使ってE2Eテストを自動化できるようにしたいと思います。
Protractorとは
http://angular.github.io/protractor
ProtractorはAngularJS製アプリケーションのE2Eテストをするために開発された、E2Eテストフレームワークです。
AngularJSを使っていないWebサイトでもE2Eテストを実行することができます。
ProtractorはWebDriverJS(Node.jsからSeleniumを利用するためのライブラリ)を利用して実際にブラウザを操作し、テストを実行します。
導入
Node.jsのインストールをしていない場合はインストールをしてください。
インストールはこちらからできます。
Java(jdk)の確認 / インストール
本稿を執筆時ではProtractor(Seleniumサーバー)を動作させるためにJava7(jdk7)以上がインストールされている必要がありました。
まずJavaのバージョンを調べます。
$ java -version
Javaがインストールされていない、もしくは1.7以下の場合はJava(jdk)のインストールを行ってください。
Java8のインストールはこちらからできます。
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htmlこんな表示がされていればOKです。
$ javac -version java version "1.8.0_65"
Protractorのセットアップ
リポジトリをクローンしてきたら、package.jsonと同じ階層に移動して依存モジュールをインストールしましょう。
$ npm install --unsafe-perm
これでProtractorのセットアップは完了です。
Protractorをセットアップする際は、Protractorに同梱されているwebdriver-managerのupdateが必要です。しかし、package.jsonのscriptsにpostinstallを指定しておくと、npm installしたあとにpostinstallで指定したコマンドを自動で実行してくれるということを知り、今回早速使ってみました。
▼package.json
"scripts": { "postinstall": "./node_modules/protractor/bin/webdriver-manager update", "start": "./node_modules/protractor/bin/webdriver-manager start", "test": "protractor protractor.conf.js" },
テストを動かしてみる
以下のコマンドでテストが実行されます。
$ npm run test
ブラウザが立ち上がったと思いきや、すぐに閉じませんでしたか?
今の一瞬で、テストに書かれた操作がブラウザ上で実際に実行されました。今回はサンプルとして、当社のフロントエンドエンジニアメンバーのページをテスト対象としたテストコードを書いてみました。
テストの最後に、おまけでSelenium WebDriverでスクリーンショットを撮ってみています。
▼spec/gotoSpec.js
var fs = require('fs'); function writeScreenShot(data, filename) { var stream = fs.createWriteStream('./capture/' + filename); stream.write(new Buffer(data, 'base64')); stream.end(); } describe('LIG メンバーページ', function() { beforeEach(function() { var width = 1440; var height = 900; browser.driver.manage().window().setSize(width, height); // 非Angularのページの場合に必要 browser.ignoreSynchronization = true; }); it('ページタイトル', function() { browser.get('https://liginc.co.jp/member/member_detail?user=h.goto'); expect(browser.getTitle()).toEqual('後藤 寛一|メンバー | 株式会社LIG'); }); it('名前', function() { var header = element(by.css('.b_member_header--jp')); header.getText().then(function(res){ //console.log(res); expect(res).toBe('後藤 寛一'); }); var subHeader = element(by.css('.b_member_header--en')); expect(subHeader.getText()).toBe('Hirokazu Goto'); }); it('紹介文', function() { var text = element(by.css('.b_member_photo--text')); expect(text.getText()).toBe('フロントエンドエンジニアのおじいちゃんと言います。本当は24歳です。よろしくお願いします。'); }); it('ページ遷移のテスト', function() { element.all(by.css('.navi_triple--item')).get(0).click(); expect(browser.getCurrentUrl()).toBe('https://liginc.co.jp/member/member_detail?user=horiguchi'); }); it('スクリーンショットを撮る', function() { browser.takeScreenshot().then(function (png) { writeScreenShot(png, 'StrongestCSSDesign.png'); }); }) });
Protractorに用意されている多くのメソッドがPromiseを返します。
https://github.com/angular/protractor/blob/master/docs/control-flow.md#promises-and-the-control-flow
ProtractorではJasmineのexpect関数にPromiseオブジェクトが渡された場合にPromiseの解決を待ってから値の検証をしてくれるようです。
header.getText().then(function(res){ //console.log(res); expect(res).toBe('後藤 寛一'); }); // 同じ結果 expect(header.getText()).toBe('後藤 寛一');
ProtractorのAPI
今回のサンプルでは、
- ブラウザのウィンドウサイズの制御
- ページタイトルの取得
- ページ内のDOM要素にアクセスしてテキストの比較
- 取得したDOM要素のクリックしてページ遷移先の確認
などをざっくりと試してみましたが、ProtractorにはまだまだたくさんのAPIが用意されています。
本当にたくさんあるので、詳しくは公式のドキュメントを参照してください。
http://angular.github.io/protractor/#/api
configの設定例
今回の環境では以下のようにしています。
seleniumServerJarを指定することで protractor protractor.conf.jsを実行したときに、Seleniumサーバーの起動&終了を自動で行ってくれます。
selenium-server-standalone-*.jarのような指定の仕方ができないので、適宜書き換えてください。
▼protractor.conf.js
exports.config = {
//seleniumAddress: 'http://localhost:4444/wd/hub',
seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.47.1.jar',
specs: ['spec/**/*Spec.js']
//,
//capabilities: {}, // ブラウザ単体でテストする場合の設定
//multiCapabilities: [ // 複数ブラウザでテストする場合の設定
// {
// 'browserName': 'chrome'
// },
// {
// 'browserName': 'firefox'
// }
//]
};
さらに詳しい設定方法は公式のドキュメントを参照してください。
https://github.com/angular/protractor/blob/master/docs/referenceConf.js
終わりに
いかがでしたでしょうか。
前回はユニットテストの環境をご紹介しましたが、プログラムコードの実装をあまり気にしないで動作のテストができるので、E2Eテストの方が敷居がやや低いのかなという感じがしました。
参考資料
AngularJS用テストフレームワーク「Protractor」チュートリアル日本語訳
http://qiita.com/weed/items/30098f7be2f753580f63
こわくない Protractor
http://qiita.com/shuhei/items/6973fe694d29a193f224
Protractorでキャプチャを撮る
http://memo.goodpatch.co/2014/08/codepatch-003/
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。