1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

  • Gherkin syntaxを使いたい
  • AWS Lambdaで使いたい
  • 知ってる言語ベースだと更に助かる

上記の理由から、nodeで動くcucumber-jsを使ってみました。

参考にした記事

http://qiita.com/p-baleine@github/items/5e6cd1ed12e31bf7edc2
https://github.com/cucumber/cucumber-js/blob/master/docs/nodejs_example.md

##ライブラリインストール

$ npm install -S express multiline
$ npm install --save-dev cucumber@latest selenium-webdriver@3.0.1 chromedriver@2.25.1

とりあえずこんな感じに。

package.json
{
  "name": "cucumnerjs-example",
  "version": "1.0.0",
  "description": "example",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/cucumber.js",
    "start": "node index.js"
  },
  "author": "hideokamoto",
  "license": "MIT",
  "dependencies": {
    "express": "^4.14.0",
    "multiline": "^1.0.2"
  },
  "devDependencies": {
    "chromedriver": "^2.25.1",
    "cucumber": "^2.0.0-rc.6",
    "selenium-webdriver": "^3.0.1"
  }
}

##テスト用アプリの作成
テストするにはテスト対象を作らないとです。
ということで参考記事よろしくnodeで動くwebページを1つ用意します。

src/index.js
const express = require('express')
const multiline = require('multiline')
const app = express()

app.get('/', (req, res) => {
    res.send(multiline( () => {/*
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p>Cucumber-js example</p>
  </body>
</html>
  */}))
})

module.exports = app

index.js
const app = require('./src/index')

app.listen(3000, () => {
    console.log('port 3000')
})

アプリはnpm startで起動します。

$ npm start

> cucumnerjs-example@1.0.0 start /develop/node/cucumberjs
> node index.js

port 3000

テスト時に使うので、そのままにしておきましょう。

##cucumberjsでのテスト準備

cucumberjs自体はfeatureディレクトリさえあれば実行可能です。

$ mkdir features
$ npm test

> cucumnerjs-example@1.0.0 test /develop/node/cucumberjs
> cucumber.js 

0 scenarios
0 steps
0m00.000s

もっとも、テストファイルが存在しないのでただ実行しただけですが。

###Gherkinでテストを書く
とりあえずテストを書いておきましょう。

features/example.feature
Feature: Example feature
  As a user of Cucumber.js
  I want to have example application
  So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
    Given I am on the TopPage
    Then I should see "Cucumber-js example"

Featureの下3行はテスト概要などです。
Scenario以下が実際に実行するテスト内容となります。

今回は

  • Given I am on the TopPage
  • Then I should see "Cucumber-js example"

の2つをテストするということですね。

この状態でテストを実行すると、以下のように「対応するコードがない」というエラーが出てきます。

Feature: Example feature

    As a user of Cucumber.js
    I want to have documentation on Cucumber
    So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
  ? Given I am on the TopPage
  ? Then I should see "Cucumber-js example"

Warnings:

1) Scenario: I am on the TopPage - features/documentation.feature:6
   Step: Given I am on the TopPage - features/documentation.feature:7
   Message:
     Undefined. Implement with the following snippet:

       Given('I am on the TopPage', function (callback) {
         // Write code here that turns the phrase above into concrete actions
         callback(null, 'pending');
       });

2) Scenario: I am on the TopPage - features/documentation.feature:6
   Step: Then I should see "Cucumber-js example" - features/documentation.feature:8
   Message:
     Undefined. Implement with the following snippet:

       Then('I should see {arg1:stringInDoubleQuotes}', function (arg1, callback) {
         // Write code here that turns the phrase above into concrete actions
         callback(null, 'pending');
       });

1 scenario (1 undefined)
2 steps (2 undefined)
0m00.000s
npm ERR! Test failed.  See above for more details.

「こういう風にコード書いてくれ」という指示も出してくれるので、このあたりを参考にコードを書いておきましょう。

###ドライバーの設定

先にテストを実行するためのwebドライバを設定します。

features/support/world.js
require('chromedriver')
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');

function CustomWorld() {
  this.driver = new seleniumWebdriver.Builder()
    .forBrowser('chrome')
    .build();
}

defineSupportCode(function({setWorldConstructor}) {
  setWorldConstructor(CustomWorld)
})

###step_definitionsの設定
続いてGherkinに対応するstep_definitionsを記述します。

features/step_definitions/browser_steps.js
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');

defineSupportCode(function({Given, Then}) {
    Given('I am on the TopPage', function () {
      return this.driver.get('http://localhost:3000');
    });
    Then('I should see {stringInDoubleQuotes}', function (text) {
        const xpath = "//*[contains(text(),'" + text + "')]"
        const condition = seleniumWebdriver.until.elementLocated({xpath: xpath})

        return this.driver.wait(condition, 10000)
    });
});

###hookの設定
features/support/hooks.jsへ、scenarioの前後に実行したいコードを書くことができます。

var {defineSupportCode} = require('cucumber');

defineSupportCode(function({After}) {
  After(function() {
    return this.driver.quit();
  });
});

##テストを実行

お待たせしました。いよいよテスト実行の瞬間です。
事前にnpm startlocalhost:3000にアクセスできることを確認しておきましょう。

$ npm test

> cucumnerjs-example@1.0.0 test /develop/node/cucumberjs
> cucumber.js

Feature: Example feature

    As a user of Cucumber.js
    I want to have documentation on Cucumber
    So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
  ✔ Given I am on the TopPage
  ✔ Then I should see "Cucumber-js example"

1 scenario (1 passed)
2 steps (2 passed)
0m01.406s

成功しました。

###テストを失敗させる

せっかくなので、テスト失敗のケースも見ます。
src/index.js内のコンテンツを書き換えて、npm startを再実行します。

src/index.js
const express = require('express')
const multiline = require('multiline')
const app = express()

app.get('/', (req, res) => {
    res.send(multiline( () => {/*
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p>Fail test pattern</p>
  </body>
</html>
  */}))
})

module.exports = app

テストを実行してみましょう。

$ npm test

> cucumnerjs-example@1.0.0 test /develop/node/cucumberjs
> cucumber.js

Feature: Example feature

    As a user of Cucumber.js
    I want to have documentation on Cucumber
    So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
  ✔ Given I am on the TopPage
  ✖ Then I should see "Cucumber-js example"

Failures:

1) Scenario: I am on the TopPage - features/example.feature:6
   Step: Then I should see "Cucumber-js example" - features/example.feature:8
   Step Definition: features/step_definitions/browser_steps.js:8
   Message:
     Error: function timed out after 5000 milliseconds
         at Timeout.<anonymous> (/develop/node/cucumberjs/node_modules/cucumber/lib/user_code_runner.js:91:22)
         at ontimeout (timers.js:365:14)
         at tryOnTimeout (timers.js:237:5)
         at Timer.listOnTimeout (timers.js:207:5)

1 scenario (1 failed)
2 steps (1 failed, 1 passed)
0m06.392s
npm ERR! Test failed.  See above for more details.

失敗しました。

##使ってみて

step_definitionsを自前で書かないといけないのがちょっとツラいなという感じがあります。
BehatであればMinkExtensionを入れるだけでそこそこ使える感じになっていたという印象がありますので。

・・・なんてことを脳内でボヤいていたら、ありました。
https://www.npmjs.com/package/cucumber-mink

次回はこれを使ってみようと思います。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?