Node.jsでBrowserStack Automateを使ってテスト

## BrowserStack とは
[BrowserStack](http://www.browserstack.com/) とは、クロスブラウザ(OS含む)による動作確認を手軽に行える環境を提供しているサービスです。
例えば、BrowserStack 側のサーバで起動している各種ブラウザ環境を、こちらのブラウザから利用したりすることができます。

その中に [Automate](https://www.browserstack.com/automate) という、コードからその環境を利用できる仕組みがあり、今回はそれを Node.js から使ってみたいと思います。


## 当記事のゴール
- Travis CI 上で、
- express アプリケーションを起動し、
- mocha で書いたテストコードを使い、
- BrowserStack Automate 環境で、

テストが出来ること。


## BrowserStack アカウントを作成する
まずはアカウントの作成が必要になるので、[トップページ](http://www.browserstack.com/) から道なりに登録してください。
メールアドレスとパスワードだけで登録でき、ある程度の時間は無料で使えます。当記事をお読みになって、ちょっと検証してみたいなーという程度なら充分な時間です。

一応、自分が行った登録手順を軽く書いておきます:

1. http://www.browserstack.com/
2. 左上 FREE TRIAL から Sign up
3. AUTOMATE タブ → Start（？だっけ、忘れた）道なりにボタン押す

登録すると、左上らへんに "Username and Access Keys" というのがあると思うので、発見しておいて下さい。


## 解説用リポジトリを clone する
https://github.com/kjirou/browserstack-with-express へ解説と検証用のリポジトリを作成したので、手元で動かしたい方は clone して貰うと楽です。
すげー基本的なことしかやってないので、clone しないで、説明の際にリンクする先のソースコードを読むだけでも充分だと思います。

clone した方は、以下の初期設定を行って下さい:

```bash
npm install
cp browserstack-conf.example.json browserstack-conf.json
# 自分の Username と Access Keys に書き換える
vi browserstack-conf.json
```

ちなみに、こちらの Node.js 用マニュアルはとても良く出来ています。
https://www.browserstack.com/automate/node

とても良く出来てるので、わざわざ自分が説明する必要あんのか感もあったりします..


## グローバルなサイトをテストする
ということで、早速テストしてみましょう。

こちらのコマンドを打つと:

```bash
node bin/run-simple-global-site-test.js
```

このような出力になり:

```bash
BrowserStack - Google Search
```

（実際の結果は、Google サイト側の仕様で変わったりするので、違う出力になっても気にしないでください。）

https://www.browserstack.com/automate へ、以下のようなテスト結果が生成されていると思います。

![](http://i.gyazo.com/2b9815733e24ab51cff1d8a20425d3d8.png)

[run-simple-global-site-test.js](https://github.com/kjirou/browserstack-with-express/blob/master/bin/run-simple-global-site-test.js) が何をしているかと言うと、以下の一連の動作です。

1. http://www.google.com/ を Windows の Firefox で開く
2. 検索フォームに "BrowserStack" を入力する
3. 検索ボタンを押して検索結果画面へ遷移する
4. 遷移後のページタイトルを取得して console.log で出力する
5. その結果を、BrowserStack 側がテスト結果として保存する

こんな感じにテストが出来ます、ということです。


## ローカルなサイトをテストする
先ほどは、グローバル環境で動いている Google トップページを検証しましたが、アプリケーションの開発中であれば通常はローカル環境をテストしたいと思います。

BrowserStack はその点もサポートしており、ローカル環境に仲介をするプロキシみたいなプロセス（？表現は適当でないかも）を起動しておくことで、外部の BrowserStack サーバへ接続してテストを実行することが可能になっています。

https://www.browserstack.com/automate/node#setting-local-tunnel に各環境用のコマンドが配置してあるので、bin 直下においてください。

もし Mac なら、以下を実行してもいいです:

```bash
cd bin
wget https://www.browserstack.com/browserstack-local/BrowserStackLocal-darwin-x64.zip
unzip BrowserStackLocal-darwin-x64.zip
rm BrowserStackLocal-darwin-x64.zip
```

では、テストをはじめます。

まずは、ローカル環境の express アプリケーションサーバを起動します。

```bash
npm start
```

http://localhost:3000/ で "Express" と表示されていれば OK です。
表示されていなかったら.. 各自頑張ってください！

次に、先ほど配置した `BrowserStackLocal` プロセスを起動します:

```bash
bin/BrowserStackLocal あなたのAccessKey localhost,3000,0
```

これで準備が整いましたので、以下のコマンドを実行してください:

```
node bin/run-simple-local-site-test.js
```

"Express" と出力され、https://www.browserstack.com/automate で以下のテスト結果が確認できると思います:

![](http://i.gyazo.com/83dfe941137712e11219dd12474ee7da.png)

[run-simple-local-site-test.js](https://github.com/kjirou/browserstack-with-express/blob/master/bin/run-simple-local-site-test.js) については、賢明なる諸氏に対してもう細かい説明は不要だと思うので、ポイントだけ列挙します。

- Visual Logs で画像を出すには `'browserstack.debug' : 'true'`
- ローカル環境をテストする場合は `'browserstack.local' : 'true'`


## テストコードを mocha で書く
今までは素の node スクリプトでテストを書いていましたが、mocha 形式で書いてみます。
そして、外側で起動していた express アプリケーションのプロセスを、テスト内で管理できるようにしてみます。

まず、https://www.browserstack.com/automate/node#mocha に記載のあるように `selenium-server-standalone.jar` へのパスを `$SELENIUM` 環境変数へ設定する必要があります。

[本家](http://www.seleniumhq.org/download/) からDLして適当な場所に置くのが最も簡単だと思いますが、一応自分がやった Homebrew の例を記載しておきます。
バージョンはドキュメントと厳密に合わせなくても良いようです:

```
brew install selenium-server-standalone
export SELENIUM='/usr/local/Cellar/selenium-server-standalone/2.43.1/bin/selenium-server'
```

次に、先のテストで実行した express と BrowserStackLocal プロセスは落とし、後者のみポート番号を変えて再度起動します（ポート番号を変えたのは、アプリの3000番と競合しないためという一般的な理由です）:

```bash
bin/BrowserStackLocal あなたのAccessKey localhost,3001,0
```

ローカルインストールされている mocha コマンドで実行します:

```
./node_modules/.bin/mocha test/minimum-e2e.js
```

以下の様な結果になり、BrowserStack 側にもテスト結果が生成されていれば成功です:

```
  minimum e2e
Express server listening on port 3001
GET / 200 256.862 ms - 170
GET /stylesheets/style.css 200 6.326 ms - 110
    ✓ should title be "Express" (187ms)
Close express server listening


  1 passing (13s)
```

console.log や Webサーバのログが出ているが邪魔ですが、通常の mocha のテスト結果です。

[test/minimum-e2e.js](https://github.com/kjirou/browserstack-with-express/blob/master/test/minimum-e2e.js) のポイントです:

- **非同期実行は done コールバックによる管理ではなく、[WebDriverJS](https://code.google.com/p/selenium/wiki/WebDriverJs) によって管理される** 、done を仮引数に取っても常に undefined
  - 自分も使い方が良くわかっていませんが、書いてある `defer` の処理がわかれば当面はどうにかなりそう
  - `driver.*` 関数群が同期的に書けるのは、中で WebDriverJS の promise の管理をしているから
- `driver.quit()` は常にテストコードの最後に実行されるようにすること
- `test.*` はインストールしている mocha をラップした関数群
  - 元の mocha 仕様をどの程度再現出来ているかは不明


なお、https://www.browserstack.com/automate/node#testing-frameworks にあるように、他テスティングフレームワークを選択することも可能なようです。
自分は、手馴れているので mocha にしましたが、WebDriverJS と親和性の高いものにした方がいいような気もしています。


## Travis CI 上で mocha テストを動かす
先の mocha テストケースを Travis CI 上で動かしてみます。

テスト結果については、上記と同じなので特に補足することはありません。
設定上の注意はありますが、[.travis.yml](https://github.com/kjirou/browserstack-with-express/blob/master/.travis.yml) にコメントで書いた程度の一般的なものです。

.. 落とし穴はあると思いますが、残念ながらまだ落ちていません。


## 以上です
BrowserStack の中身について検証する前に記事が長くなりすぎたので、ここまでにしました。

自分は、以下の様な点が気になっています。
速攻調べられるようなこともメモ替わりに書き殴ります:

- BrowserStack 側のプロジェクトの作り方
  - それをこちらのプロジェクトへ関連付けする方法
- ひとつのブラウザのみエラーになった場合、テストケース側は失敗になるのか？
  - テストケース側の出力はどうなるんだろう？
- クライアント側のJSエラーの拾い方は
- `driver.quit()` の後に別の `describe` で `driver` インスタンスを生成しても大丈夫？
  - WebDriverJSのPromiseの仕組みが良くわかってないから不安


## 次は..

[Node.js Advent Calendar](http://qiita.com/advent-calendar/2014/nodejs)、明日は @gologo13 さんです！