Grunt+Protractor+karma+JasmineでGAE+Angular.jsのテスト環境構築の際のメモ


# 前提
karmaでe2eテストまでやろうと思ってたけど、

> 　Angular Scenario Runner is in maintenance mode - If you're starting a new Angular project, consider using Protractor.

とのことなので、e2eのほうはProtractorを導入することにした。
GAEとか使ってないよの場合は適宜読み替えて。

テストのシナリオ

1. ローカルでまっさらなGoogle App Engineのアプリケーションを起動
2. Protractorからseleniumを起動
3. e2eテストをはしらせる
4. 成功しても失敗しても、Google App Engineのアプリケーションを停止
5. karmaを起動してユニットテストを実行

# 構成

要Java（seleniumのため）。

テスト関連のプラグインをパッケージに追加

``` bower.json
    "angular-mocks": "~1.2.23",
    "angular-loader": "1.2.x"
```

``` package.json
	# gaeを起動しつつ、protractorの実行をするのに使った
    "grunt-concurrent": "^1.0.0",
	# taskの前後にcontinueOn, continueOffとしておくと、その部分だけgrunt --forceしたことにしてくれる。
    "grunt-continue": "0.0.1",
    "grunt-exec": "^0.4.6",
    "grunt-gae": "^0.2.4",
    "grunt-karma": "^0.8.3",
    "grunt-open": "~0.2.2",
    "grunt-protractor-runner": "^1.1.4",
    "grunt-protractor-webdriver": "^0.1.8",
    "grunt-shell": "^1.1.1",
    "grunt-shell-spawn": "^0.3.0",
    "karma": "^0.12.23",
    "karma-chrome-launcher": "^0.1.4",
    "karma-jasmine": "^0.1.5",
    "protractor": "^1.1.1",
    "shelljs": "^0.2.6"
```

追加後

```
$ bower install
$ npm install
```

Gruntfileはこんな感じ。

```Gruntfile.coffee

module.exports = (grunt) ->

  grunt.task.loadNpmTasks 'grunt-karma'
  grunt.task.loadNpmTasks 'grunt-protractor-runner'
  grunt.task.loadNpmTasks 'grunt-exec'
  grunt.task.loadNpmTasks 'grunt-gae'
  grunt.task.loadNpmTasks 'grunt-concurrent'
  grunt.task.loadNpmTasks 'grunt-shell'
  grunt.task.loadNpmTasks 'grunt-continue'
  grunt.task.loadNpmTasks 'grunt-shell-spawn'

  grunt.initConfig
    exec:
      gaewait:
　　　　　// 起動しているか確かめる方法がなかったのでcurlで
        command: 'while ! curl http://localhost:9999 &>/dev/null; do :; done'
      webdriverstart:
        command: './node_modules/protractor/bin/webdriver-manager start > /dev/null 2>&1 &'
      webdriverwait:
        command: 'while ! curl http://localhost:4444/wd/hub/status &>/dev/null; do :; done'
      webdriverstop:
        command: 'curl -s -L http://localhost:4444/selenium-server/driver?cmd=shutDownSeleniumServer > /dev/null 2>&1'
    gae:
      start:
        action: 'run',
        options:
          path: '../'
          async: true,
          args:
            port: 9999,
            admin_port: 9001,
            clear_datastore: 'yes'
      stop:
        action: 'kill'

    concurrent:
      target:
        tasks: ["gae:start", "exec:gaewait"]
      options:
        logConcurrentOutput: true

    protractor:
      options:
        keepAlive: false,
        noColor: false
      E2E_local:
        options:
          configFile: 'js/test/protractor_conf.js',

    karma:
      unit:
        configFile: 'js/test/karma.conf.js',
        singleRun: true

  grunt.registerTask 'test', [
    'concurrent:target',
    'continueOn',
    'exec:webdriverstart',
    'exec:webdriverwait',
    'protractor',
    'exec:webdriverstop',
    'gae:stop',
    'continueOff',
    'karma',
  ]
```

karmaの設定

```karma.conf.js

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      //App-specific Code
      '../app/**/*.js',
      //Test-specific Code
      '../test/app/**/*.js'
    ],
    exclude: [
      '../lib/angular-scenario/angular-scenario.js'
    ],
    preprocessors: {
    },
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    plugins : [
            'karma-chrome-launcher',
            'karma-jasmine'
            ],
    singleRun: false
  });
};
```

protractorの設定

``` protractor_conf.js
exports.config = {
    seleniumAddress: "http://localhost:4444/wd/hub",
    capabilities: {
        browserName: "chrome"
    },
    // テスト対象のspecファイルのパス
    specs: ["e2e/**/*.js"],
    baseUrl: 'http://localhost:9999/',
    framework: "jasmine",
    jasmineNodeOpts: {
        showColors: true
    }
}

```

色々大変だったけど、動くようになりました。

```
$ grunt test
```

# 参考にした色々
- http://www.yearofmoo.com/2013/09/advanced-testing-and-debugging-in-angularjs.html
- http://angular.github.io/protractor/#/
- http://qiita.com/zoetro/items/b72130960c39055b8474
- https://github.com/angular/protractor/blob/master/docs/tutorial.md
- http://ng-learn.org/2014/02/Protractor_Testing_With_Angular_And_Non_Angular_Sites/
- http://dev.classmethod.jp/client-side/javascript/angularjs_e2e_test_protractor_introduce/