CasperJS と Nightmare と Python+WebDriver+PhantomJS でセレクトボックスを選択できるかの E2E テスト


## 目的

E2Eテストを書いていてセレクトボックス選択などでハマったりしたので、調査がてら複数のライブラリでどのように書くのか試してみる。
気になる機能も若干交えて書く。

- セレクトボックスを選択する
- セレクトボックスの選択された値を取る
- 表示しているURLを取る
- キャプチャ撮る


## CasperJS

```javascript
/*global casper*/
casper.test.begin('Test Sample', 2, function(test) {
    var selectbox = '#lang-chooser';
    var lang = 'fr';

    casper.start('https://www.google.com/doodles');

    casper.then(function() {
        var params = {};
        test.comment('change the value of the select box');

        params[selectbox] = lang;
        this.fillSelectors('#language-menu',params);

        test.assertEvalEquals(
            function(selector) {
                return document.querySelector(selector).value;
            },
            lang,
            'value of the select box has been changed',
            selectbox);
    });

    casper.then(function() {
        var comment = 'is included language type in url';
        var re = new RegExp('\\?hl=(' + lang + ')');
        test.assertMatch(this.getCurrentUrl(), re, comment);
    });

    casper.then(function() {
        this.capture('google.png');
    });

    casper.run(function() {
        test.done();
    });

});
```

実行結果

```
$ casperjs test test_google_selector.js
Test file: test_google_selector.js
# Test Sample
PASS Test Sample (2 tests)
# change the value of the select box
PASS value of the select box has been changed
PASS is included language type in url
PASS 2 tests executed in 2.477s, 2 passed, 0 failed, 0 dubious, 0 skipped.
```


## Nightmare + mocha

```javascript
/*jshint -W024 */
var Nightmare = require('nightmare');
var assert = require("assert");

describe('Test Sample', function(){
    this.timeout(15000);

    it('can change the value of the select box.', function(done){
        var selector = '#lang-chooser';
        var lang = 'fr';
        new Nightmare()
            .goto('https://www.google.com/doodles')
            .select(selector, lang)
            .evaluate(function (selector) {
                return document.querySelector(selector).value;
            }, function (select_value) {
                assert.equal(lang, select_value, 'value of the select box has been changed');
            }, selector)
            .wait(3000)
            .evaluate(function(lang) {
                var re = new RegExp('\\?hl=(' + lang + ')');
                return location.href.match(re);
            }, function(is_included_lang_in_url) {
                assert.ok(is_included_lang_in_url, 'is included language type in url');
            }, lang)

            .screenshot('google.png')
            .run(done);
    });
});
```

実行結果

```
$ node_modules/.bin/mocha test_google_selector.js


  Test Sample
    ✓ can select a select box. (3932ms)


  1 passing (4s)
```

## Python + webdriver + phantomjs

```python
from selenium import webdriver
from selenium.webdriver.support.ui import Select
import unittest


class TestSample(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.PhantomJS()
        self.driver.get('https://www.google.com/doodles')

    def tearDown(self):
        self.driver.quit()

    def test_lang_chooser(self):
        """can select a select box"""
        driver = self.driver
        selector = 'select#lang-chooser'
        lang = 'fr'

        # change the value of the select box
        element = driver.find_element_by_css_selector(selector)
        select = Select(element)
        select.select_by_value(lang)

        element = driver.find_element_by_css_selector(selector)
        self.assertEqual(
            lang, element.get_attribute("value"),
            'value of the select box has been changed'
        )

        self.assertTrue(
            '?hl={lang}'.format(lang=lang) in driver.current_url,
            'is included language type in url'
        )

        driver.save_screenshot("google.png")


if __name__ == "__main__":
    unittest.main()

```

実行結果

```
$ python test_google_selector.py -v
test_lang_chooser (__main__.TestSample)
can select a select box ... ok

----------------------------------------------------------------------
Ran 1 test in 5.608s

OK
```

## 感想

意図せず PhantomJS系のみになってしまった...。
読みやすいテストを書くにはどうすればいいんだろう。コメントとか。
E2Eテストはササッと素早く書いて実行できるものがいいのかしら。
Selenium 系の方がもっといろいろあるなぁ...

----

Casperjs

- casper.then で囲むとエラー出にくくなる。囲み過ぎるとコード冗長になるのでどこで区切るか難しい。
- コードの記述が独特。
- 情報は多そうで少ないかも。参考になりそうなコードをいろいろ見たい...。

Nightmare

- 長めに wait を入れないとエラーになる場合がある。遅過ぎてどこにwait仕込めばいいか分らなくなる時がある...。
  - とあるログイン画面で使ったら超絶遅かった
- テスト書く時はmochaとかchaiとかお好みで交える感じなのかな。このライブラリも情報少ない...。
- evaluate() が若干解り難いというか使いにくいというか。そういうものだから仕方ないのかもしれない。
- 速さが改善されてテストのサンプルコードなど情報が多ければ PhantomJS 系はこれがいいかも...

Python

- 興味本位
- コードが冗長になりそうと思ったけど CasperJS も結構冗長...。書き方次第かもだけど。
- 上手い書き方が解れば意外といいかもしれない。

----

## 参考

- http://casperjs.org/
- http://www.nightmarejs.org/
- http://selenium-python.readthedocs.org/en/latest/index.html