AngularJS でいくつかの BDD を試しているので、Protractor と CucumberJS を使用してシナリオを自動化しようとしています。奇妙なことに、ステップ定義を賢く失敗させるのは悪魔の仕事でした。
Features.feature
Feature: Calculator
As a user
I want to perform arithmetic operations
So that I don't have to think too hard
Scenario: Addition
Given I have opened the calculator application
When I add 2 and 2
Then the result 4 should be displayed
Steps.js
module.exports = function() {
this.Given(/^I have opened the calculator application$/, function (callback) {
//load protractor config baseurl
browser.get('').then(
callback());
});
this.When(/^I add (\d+) and (\d+)$/, function (arg1, arg2, callback) {
//enter numbers to be added
element(by.model('firstNumber')).sendKeys(arg1);
element(by.model('secondNumber')).sendKeys(arg2);
//select mathematical operator from dropdown list
element(by.css('select')).click();
element(by.css('select option[value="0"]')).click();
//hit the calculate button
element(by.buttonText('=')).click();
callback();
});
this.Then(/^the result (\d+) should be displayed$/, function (arg1, callback) {
element(by.binding('result')).getText()
.then(function(result){
result === arg1 ? callback() : callback.fail();
});
});
};
索引.html
<!doctype html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body ng-app="calculator" ng-controller="MainCtrl">
<input ng-model="firstNumber">
<select ng-model="selectedOperation" ng-options="op as op.value for op in operations"></select>
<input ng-model="secondNumber">
<button ng-click="Calculate()">=</button>
<span ng-bind="result"></span>
<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
App.js
angular
.module('calculator', [])
.controller('MainCtrl', function ($scope) {
$scope.operations = [
{ label: 'Add', value: '+' },
{ label: 'Subtract', value: '-' }
];
$scope.selectedOperation = $scope.operations[0];
$scope.Calculate = function(){
switch($scope.selectedOperation.label) {
case 'Add':
var result = Number($scope.firstNumber) + Number($scope.secondNumber);
break;
case 'Subtract':
var result = Number($scope.firstNumber) - Number($scope.secondNumber);
break;
};
$scope.result = result !== NaN || result === 0 ? result : 'Boo! bad input!';
};
});
分度器出力:
1 シナリオ (1 合格) 3 ステップ (3 合格)
上記の設定で問題なく動作します。分度器は正しい出力を提供し、Then() ステップで誤った結果を評価することでシナリオを失敗させることができます。いい感じ。
私が目にする最初の問題は、When ステップを失敗させようとしたときです。たとえば、上記と同じ設定を使用して、存在しない要素を見つけようとしています。
this.When(/^I add (\d+) and (\d+)$/, function (arg1, arg2, callback) {
//enter numbers to be added. Sabotage edition!
element(by.model('AintNoGood')).sendKeys(arg1);
element(by.model('secondNumber')).sendKeys(arg2);
//select mathematical operator from dropdown list
element(by.css('select')).click();
element(by.css('select option[value="0"]')).click();
//hit the calculate button
element(by.buttonText('=')).click();
callback();
});
分度器の出力: NoSuchElementError: ロケーターを使用して要素が見つかりません: by.model("AintNoGood") ... 1 つのシナリオ (1 つが失敗) 3 つのステップ (1 つが失敗、2 つが成功)
2 番目のステップは正しく失敗します。ステップが失敗すると、後続のすべてのステップがスキップされるという印象を受けますが、分度器はとにかく通過する3番目のステップに進みます。
まだ見知らぬ人...私は HTML を空にします。BDDテストファーストとすべて。
Inmdex.html
<!doctype html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body ng-app="calculator" ng-controller="MainCtrl">
<!--Ghost town here-->
<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
シナリオを 1 ステップずつ実行していると仮定して、失敗すると仮定して 2 番目のステップの定義を記述します。
module.exports = function() {
this.Given(/^I have opened the calculator application$/, function (callback) {
//load protractor config baseurl
browser.get('').then(
callback());
});
this.When(/^I add (\d+) and (\d+)$/, function (arg1, arg2, callback) {
//enter numbers to be added
element(by.model('firstNumber')).sendKeys(arg1);
element(by.model('secondNumber')).sendKeys(arg2);
//select mathematical operator from dropdown list
element(by.css('select')).click();
element(by.css('select option[value="0"]')).click();
//hit the calculate button
element(by.buttonText('=')).click();
callback();
});
this.Then(/^the result (\d+) should be displayed$/, function (arg1, callback) {
callback.pending();
});
};
分度器の出力: 1 つのシナリオ (1 つの保留中) 3 つのステップ (1 つの保留中、2 つの合格)
したがって、2 番目のステップはパスします。明らかに、html に配置されているはずの要素がない場合は、そうすべきではありません。
質問:
ここで何が起こっているのか分かりますか?
そうでない場合は、それを理解するためにもっと時間を費やす前に、誰かが CucumberJS で分度器を使用して成功したかどうか疑問に思っていますか?