AngularJSにE2Eテスト環境としてProtractorを導入する。

AngularJS

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

AngularJS Generatorで作成した雛形にはE2Eテスト環境を作ろうとした形跡は見られるのですが、実際にGruntのタスクとしては登録されておらず、E2Eテストは行えない状態です。

また、E2Eテスト環境も現在では非推奨であるAngular Scenario Runnerを用いた形の為、
現在AngularJS側も推奨をしているProtractorを導入します。

導入方法

AngularJS Generatorを用いて雛形を作成します。
雛形作成に関しては、下記の記事を参照ください。

Yeomanを使ってAngularJSアプリのひな形をつくってみる

Protractorとgrunt-protractor-runnerを導入

$ npm install --save-dev protractor grunt-protractor-runner
$ node node_modules/protractor/bin/webdriver-manager update

Protractorの設定ファイルを作成

AngularJS Headless End to End Testing With Protractor and Selenium 内にあるprotractor.conf.jsを
コピペして以下を変更しました。

Protractor.conf.js

// seleniumAddress: 'http://selenium.example.com:4444/wd/hub',
//Chromedriverで動かないよとの事が記載されているが、現行動いたので、コメントアウト

specs: [
    'test/e2e/**/*.js'
  ],
//karma-e2e.conf.jsとパスを合わせた。

baseUrl: 'http://localhost:9000',
//gruntで立ち上がるローカルサーバーを参照するように変更

Gruntタスクの設定

Gruntfile.js

//E2Eテストランナー protractorのタスク設定です。
        protractor: {
            options: {
                configFile: 'node_modules/protractor/referenceConf.js', // Default config file
                keepAlive: false,
                noColor: false,
                args: {}
            },
            E2E_local: {
                options: {
                    configFile: 'protractor.conf.js',
                    args: {}
                }
            }
        }

テスト対象コードを作成

app/view/main.html

<div class="jumbotron">
  <h1>'Allo, 'Allo!</h1>
  <p class="lead">
    <img src="images/yeoman.png" alt="I'm Yeoman"><br>
    Always a pleasure scaffolding your apps.
  </p>
  <p><a class="btn btn-lg btn-success" ng-href="#">Splendid!<span class="glyphicon glyphicon-ok"></span></a></p>
  <p><a class="btn btn-lg btn-success" ng-click="click()">Add List<span class="glyphicon glyphicon-ok"></span></a></p>
</div>
<div class="row marketing" ng-if="visibleList">
  <ul id="awesomeThings" ng-repeat="awesomeThing in awesomeThings">
    <li>{{awesomeThing}}</li>
  </ul>
</div>

app/scripts/controllers/main.js

'use strict';

angular.module('angularE2EApp')
    .controller('MainCtrl', function($scope) {
        $scope.click = function () {
            $scope.visibleList = true;
        };
        $scope.visibleList = false;
        $scope.awesomeThings = [
            'HTML5 Boilerplate',
            'AngularJS',
            'Karma'
        ];
    });

実装内容としては、show listボタンを押下すると、
$scope.awesomeThingsに設定した項目が表示されるといった実装になります。

E2Eテストコードの作成

E2Eテストを配置するディレクトリがないため作成します。

$  mkdir test/e2e

test/e2e/mainE2Etest.js

'use strict';
describe('E2ETestSample',function () {
    beforeEach(function () {
        browser.get('/#/');
    });
    it('ボタン押下後、3つのリストが出る事の確認',function () {
       expect(element.all(by.repeater('awesomeThing in awesomeThings')).count()).toEqual(0);
        var button = browser.findElement(by.css('#ShowListBtn'));
        button.click();
        expect(element.all(by.repeater('awesomeThing in awesomeThings')).count()).toEqual(3);
    });
});

テスト内容としては、ボタン押下前にはリストの個数が0個の事をテストし、
ボタン押下後リストの個数が3個に増えていることを確認しています。

テスト実施

テスト対象コードを含んだページを立ち上げます。

$ grunt serve

別途シェルを立ち上げて、E2Eテストを実施します。

$ grunt protractor:E2E_local

Chromeが立ち上がり、自動的にテストが実施されます。

AngularE2ETest

最後に

ProtractorがAngularJS向けに作られたテスト用のフレームワークという事もあり、 ngRepeatを用いてBindingした項目を容易に取得する事ができる点などが非常に特徴的でした。

また、ProtractorはSelenium WebdriverJS上に構築されたアプリケーションのため、
Appium を用いてiOSやAndroidの実機を用いたテスト等もできるようです。
その辺りも今後紹介できればと思います。

参考サイト