ProtractorでAngularアプリのE2Eテストやってみた、PhantomJS編

  • 投稿日:
  • by

過去にKarma(Testacular)を使ったことはありますが、今回やっと時代に追いついてProtractorを使ってみました。特にPhantomJSを使ってheadlessでE2Eテストするときに気づいたことをまとめます。

Protractorは、 SeleniumWebDriverJSのラッパーで、AngularJSのE2Eテストのためのフレームワークです。

https://docs.angularjs.org/guide/e2e-testing

がエントリーポイントになるでしょう。 しかし、これだけ読んでも最終的な実行方法は分かりづらいです。 今回の目的は、コマンド一つ、例えば、

$ npm run e2e-test

でE2Eテストを実行してするための環境セットを作ることです。また、headlessで動かしたかったので、典型的に使われるChromeではなく、PhantomJSを前提にしました。サーバはExpress/Node.jsの想定ですが、それ以外の場合にも応用できるかと思います。

初めによくある環境設定です。

$ npm install protractor
$ npm install phantomjs
$ ./node_modules/.bin/webdriver-manager update

この例ではローカルディレクトリにモジュールをインストールしていますが。グローバルにインストールしたい人はそのようにどうぞ。

まず初めにはまったことはwebdriverが起動しないことでした。

$ ./node_modules/.bin/webdriver-manager start
INFO - Launching a standalone server
WARN - null
java.net.SocketException: No such device
    at java.net.NetworkInterface.isLoopback0(Native Method)

このようなエラーがでました。ワーニングかと思って無視していたらいけませんでした。どうやら、IPv6のアドレスのみを使っていてうまく行かないようだったので、Javaのオプションを追加して次のようにするとうまく行くことが分かりました。

$ env _JAVA_OPTIONS=-Djava.net.preferIPv4Stack=true ./node_modules/.bin/webdriver-manager start

さて、Protractorのチュートリアルには、webdriverをコマンドラインで手動で実行するように書いてありますが、個人的にはこれは面倒に感じます。時間はかかりますが、毎回自動で起動して欲しいです。これは簡単で、protractor.conf.jsにseleniumAddressを書かなければよいだけでした。下記に、protractor.confを載せます。

exports.config = {
  specs: [
    '*-spec.js'
  ],
  capabilities: {
    'browserName': 'phantomjs',
    'phantomjs.binary.path': './node_modules/.bin/phantomjs'
  },
  baseUrl: 'http://localhost:' + (process.env.PORT || 3000) + '/'
};

これだけで大丈夫でした。baseUrlは、specにURLをフルパスで書かなくてもよいようにするためで、expressが下記のように起動されている想定です。

app.listen(process.env.PORT || 3000);

specの細かい内容は今回は書きませんが、もっとも単純なものは例えば次のようになります。

describe('tutorial', function() {
  it('should have a title', function() {
    browser.get('index.html');
    expect(browser.getTitle()).toEqual('The Title');
  });
});

ところで、Protractorはテストのフレームワークであるもののアプリの起動には関与せず、アプリは自分で起動しなければいけません。また、テスト終了後はアプリも終了したいです。今回はお手軽にシェルスクリプトを書きました。

#!/bin/sh

export _JAVA_OPTIONS=-Djava.net.preferIPv4Stack=true
export PORT=12345
node ./app.js &
PID=$!
./node_modules/.bin/protractor ./e2e-test/protractor.conf.js
kill $PID

このスクリプトをpackage.jsonのscriptsに書いておけば、当初の目的であったnpmで一発でE2Eテストを走らせることができました。

Happy e2e testing!