WebdriverIO + power-assert でe2eテストをgeneratorで書いてみる

[WebdriverIO](http://webdriver.io/)は、ES6 generators (yield)を利用してテストが書けるので、[power-assert](https://github.com/power-assert-js/power-assert)と組み合わせてテストを書いてみた。

# 準備

gulpで環境構築する[サンプル](https://github.com/yoshi6jp/webdriverio-power-assert-sample)を作ったので`git clone`...

```
$ git clone git@github.com:yoshi6jp/webdriverio-power-assert-sample.git
$ cd webdriverio-power-assert-sample/
$ npm install
```

# とりあえず、実行してみる

```
$ npm test

> wdio@1.0.0 test webdriverio-power-assert-sample
> gulp

[07:00:45] Requiring external module coffee-script/register
[07:00:46] Using gulpfile webdriverio-power-assert-sample/gulpfile.coffee
[07:00:46] Starting 'selenium-install'...
[07:03:51] Finished 'selenium-install' after 3.08 min
[07:03:51] Starting 'selenium'...
[07:03:51] Finished 'selenium' after 592 ms
[07:03:51] Starting 'webdriver'...
[07:03:51] spawn wdio with these attributes:
 webdriverio-power-assert-sample/wdio.conf.js

․․․․

4 passing (25.60s)


[07:04:18] wdio testrunner finished with exit code 0
[07:04:18] Finished 'webdriver' after 26 s
[07:04:18] Starting 'default'...
[07:04:18] Finished 'default' after 579 μs

```
- Selenium Webdriverのダウンロード、インストール、起動もgulpでやってます
- firefoxが起動して、テストが実行されるはず...

# 解説

## generatorの例 
- ほぼ、[WebdriverIO](http://webdriver.io/)のサンプルそのままですが。。。

```js
var assert = require('power-assert');
// :
describe('js test case', function() {
  before(function(){
    browser.url('http://webdriver.io');
  })
  it('generator', function* () {
    // function* でgeneratorの宣言

    var title = yield browser.getTitle();   
    //yieldでtitleの値を取得

    assert(/WebdriverIO/.test(title) == true);
  });
  // :    
});
```
- power-assertなのでエラー時もきれいに表示(`assert(title == "ng")`を追加して実行)

```
AssertionError:   # test/specs/case1.js:15
  
  assert(title == "ng")
         |     |       
         |     false   
         "WebdriverIO - Selenium 2.0 javascript bindings for nodejs"
```
## [Custom Commands](http://webdriver.io/guide/usage/customcommands.html)を使ってみる

- 独自のコマンドを`browser`オブジェクトに追加して利用できる

### promise版
```js
browser.addCommand("getUrlAndTitle", function() {
    return this.url().then(function(urlResult) {
        return this.getTitle().then(function(titleResult) {
            return { url: urlResult.value, title: titleResult };
        });
    });
});
```

### generator版

```js
// この記述だとエラーになる
browser.addCommand("getUrlAndTitle", function* () {
  var urlResult = yield this.url();
  var titleResult = yield this.getTitle();
  return { url: urlResult.value, title: titleResult };
});
```
- addCommandは、promiseしか対応していないので、単純に`function*`でgeneratorを書くとエラーに...

カスタムコマンドでもgeneratorを使いたいので、[co]("https://github.com/tj/co")を使って解決!
####　解決方法
```js
var co = require('co');
browser.addCommand("getUrlAndTitle", co.wrap(function* () {
  var urlResult = yield this.url();
  var titleResult = yield this.getTitle();
  return { url: urlResult.value, title: titleResult };
}));
```
- `co.wrap`を使うと`generator`を`promise`に変換できる

```js
var assert = require('power-assert');
var co = require('co');
browser.addCommand("getUrlAndTitle", co.wrap(function* () {
  var urlResult = yield this.url();
  var titleResult = yield this.getTitle();
  return { url: urlResult.value, title: titleResult };
}));
describe('js test case', function() {
  before(function(){
    browser.url('http://webdriver.io');
  })
  it('custom command', function* (){
    var urlAndTitle = yield browser.getUrlAndTitle();
    // カスタムコマンドを実行してyieldで値を取得

    assert(/WebdriverIO/.test(urlAndTitle.title) == true);
    assert(urlAndTitle.url == 'http://webdriver.io/');
  });
});
```

## coffeescriptでも書いてみる

```coffeescript
assert = require 'power-assert'
co = require 'co'
browser.addCommand "getUrlAndTitleCS", co.wrap ->
  urlResult = yield this.url()
  titleResult = yield this.getTitle()
  url: urlResult.value, title: titleResult

describe 'cs test case', ->
  before ->
    browser.url 'http://webdriver.io'

  it 'generator', ->
    title = yield browser.getTitle()
    assert /WebdriverIO/.test(title) == true

  it 'custom command', ->
    urlAndTitle = yield browser.getUrlAndTitleCS()
    assert /WebdriverIO/.test(urlAndTitle.title) == true
    assert urlAndTitle.url == 'http://webdriver.io/'

```
- [coffeescript](http://coffeescript.org/#fat-arrow)の場合、`->`演算子の中に`yield`があると`generator`と解釈してくれるので、少し便利!

### 他のブラウザでテストする場合

[weio.conf.js](http://webdriver.io/guide/getstarted/configuration.html)を編集することで可能

```js
   capabilities: [{
        browserName: 'firefox' 
        // -> 'chrome' or 'internet explorer', etc
    }],
```

- 他にも色々とカスタマイズできる