美文网首页
CucumberJS

CucumberJS

作者: xiaojuanxu | 来源:发表于2018-11-29 17:30 被阅读0次

Cucumber.js是用JavaScript实现的Cucumber,可以运行在Node.js(4.0及以上版本)和现代web浏览器上。

Install

npm install cucumber

Notes: Cucumber不能全局安装,因为使用时需要在support files中引用cucumber,而全局安装的模块是无法被引用的。

CLI

Running specific features

  • 运行全部的feature
    • $ cucumber-js features/**/*.feature
  • 运行特定文件夹下的feature
    • $ cucumber-js features/dir
  • 运行特定的feature
    • $ cucumber-js features/my_feature.feature
  • 运行一个特定的Scenario根据它所在的行数
    • $ cucumber-js features/my_feature.feature:3
  • 运行一个特定的Scenario根据它的名字
    • $ cucumber-js --name "topic 1"
  • Tags

Requiring support files

在运行features前,用--require <GLOB|DIR|FILE>来引用support file。

  • node-glob
  • 如果不使用GLOB模式,则需要自定义support文件,见下文

Formats

--format <TYPE[:PATH]>可以指定输出的格式。如果PATH没有指定,则输出到默认文件中。否则输出到PATH指定的文件。format可以同时指定多个,输出不同格式的结果到不同的文件中。

  • Q1: 不指定PATH的时候,stdout指向哪里?
  • Q2: 如何同时指定多个format到多个file?

内置的几种格式:event-protocol, json, progress, progress-bar, rerun, snippets, summary, usage, usage-json

rerun -- prints the paths of any non passing scenarios(example)

Format Options

可以使用 --format-options <JSON> 指定format 参数.

建议的用法: 创建profile文件(见后续),在其中定义一些json对象,用 JSON.stringify调用,避免直接写JSON.

For example:

//cucumber.js
const formatOpt = { "colorEnabled": true };

exports = module.exports = {
    default: `--compiler es6:babel-core/register --format-options '${JSON.stringify(formatOpt)}'`
}

Colors

--format-options '{"colorsEnabled": false}'可以使colors失效。

Exiting

使用--exit可以在测试运行结束时强制退出,但是不建议这么使用。

Undefined Step Snippets

未定义的step片段会默认使用回到接口打印到javascript中。
重写代码片段可以使用--format-options '{"snippetInterface": "<interface>"}'。有效的interface有async-await, callback, generator, promise 或者 synchronous。

Rerun separator

rerun格式的分隔符可以重新指定--format-options '{"rerun": {"separator": "<separator>"}}'

默认的分隔符是一个newline charactor,当我们需要在本地从CLI日志中复制一行重新运行那些失败的测试而分隔符是一个space charactor时,这个属性是有用的。

需要注意的是,rerun file的分隔符只能是默认的分隔符。

Parallel

使用--parallel <NUMBER_OF_SLAVES>我们可以同时并行多个scenarios。每一个slave都是一个独立的node进程并接受下列变量:

  • CUCUMBER_PARALLEL - set to 'true'
  • CUCUMBER_TOTAL_SLAVES - set to the number of slaves
  • CUCUMBER_SLAVE_ID - id for slave

**Note: **在使用parallel的时候,打印stdout(比如 console.log)会报错,因为每个从进程会通过stdout与主进程通信。

Profile

为了存放和重用那些常用的CLI options,我们可以在根目录下添加一个cucumber.js的文件,把options写在其中。Profile可以通过-p <NAME>--profile <NAME>来调用。

Tags

cucumber tag expression

Transpilers

Step definitions 和 support file可以用其它语言编写,然后转译成javascript。为了达到这个目的,可以使用--require-module <module_name>

World Parameters

我们可以把一些parameter传递到 world constructor中,使用--world-parameter <JSON>. The JSON string必须定义一个对象。

Support Files

World

对每个scenario,World都是一个独立的上下文,暴露给hooks和steps就是this。默认的world构造函数:

function World({attach, parameter}) {
    this.attach = attach
    this.parameters = parameters
}
  • attach: 用于向hooks/steps添加attachments
  • parameters: 就是通过CLI传递的参数对象

默认的World可以被覆盖通过setWorldConstructor:

var {setWorldConstructor} = require('cucumber');
var seleniumWebdriver = require('selenium-webdriver');

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

this.waitForElement = function(locator) {
    var condition = seleniumWebdriver.until.elementLocated(locator);
    return this.driver.wait(condition);
}

setWorldConstructor(CustomWorld);

Hooks

Hooks用于运行每一个scenario前后setup和teardown环境。Multiple Before hooks可以按定义顺序依次执行,而 Multiple After hooks则按照他们定义的顺序反向执行。

var {After, Before} = require('cucumber');

// Synchronous
Before(function () {
  this.count = 0;
});

// Asynchronous Callback
Before(function (testCase, callback) {
  var world = this;
  tmp.dir({unsafeCleanup: true}, function(error, dir) {
    if (error) {
      callback(error);
    } else {
      world.tmpDir = dir;
      callback();
    }
  });
});

// Asynchronous Promise
After(function () {
  // Assuming this.driver is a selenium webdriver
  return this.driver.quit();
});

Tagged hooks

var {After, Before} = require('cucumber');

Before(function () {
  // This hook will be executed before all scenarios
});

Before({tags: "@foo"}, function () {
  // This hook will be executed before scenarios tagged with @foo
});

Before({tags: "@foo and @bar"}, function () {
  // This hook will be executed before scenarios tagged with @foo and @bar
});

Before({tags: "@foo or @bar"}, function () {
  // This hook will be executed before scenarios tagged with @foo or @bar
});

// You can use the following shorthand when only specifying tags
Before("@foo", function () {
  // This hook will be executed before scenarios tagged with @foo
});

BeforeAll/AfterAll

如果需要在所有的scenario前后setup/teardown环境,可以使用BeforeAll/AfterAll。像hooks和steps一样,她们可以是异步的?同步的?接收callback,返回一个promise

Notes 不同于Before/After,这些方法不能接收world 实例作为this,这是因为每一个scenario都会拥有一个属于自己的world实例。

var {AfterAll, BeforeAll} = require('cucumber');

// Synchronous
BeforeAll(function () {
  // perform some shared setup
});

// Asynchronous Callback
BeforeAll(function (callback) {
  // perform some shared setup

  // execute the callback (optionally passing an error when done)
});

// Asynchronous Promise
AfterAll(function () {
  // perform some shared teardown
  return Promise.resolve()
});

Timeout

默认情况下,异步的hooks和steps会在5000ms后超时,这个默认值也可以全局修改:

const setDefaultTimeout = require('cucumber');
setDefaultTimeout(60*1000);

也可以为一个特定的hook或者step设定timeout:

var {Before, Given} = require('cucumber');

Before({timeout: 60 * 1000}, function() {
  // Does some slow browser/filesystem/network actions
});

Given(/^a slow step$/, {timeout: 60 * 1000}, function() {
  // Does some slow browser/filesystem/network actions
});

也可以选择disable掉timeout设置通过设置timeout的值为-1,但相应的要定义自己的超时保护机制,否则测试会意外退出或永久挂起:

var {Before, Given} = require('cucumber');
var Promise = require('bluebird');

Given('the operation completes within {n} minutes', {timeout: -1}, function(minutes) {
  const milliseconds = (minutes + 1) * 60 * 1000
  const message = `operation did not complete within ${minutes} minutes`
  return Promise(this.verifyOperationComplete()).timeout(milliseconds, message);
});

Data tables

Data tables分为有header和无header两种,具体使用可以参照example

  • with column header
Scenario: rows
    Given a file named "features/passing_steps.feature" with:
      """
      Feature: a feature
        Scenario: a scenario
          Given a table step
            | Vegetable | Rating |
            | Apricot   | 5      |
            | Brocolli  | 2      |
            | Cucumber  | 10     |
      """
    Given a file named "features/step_definitions/passing_steps.js" with:
      """
      import {Given} from 'cucumber'
      import assert from 'assert'
      Given(/^a table step$/, function(table) {
        const expected = [
          ['Apricot', '5'],
          ['Brocolli', '2'],
          ['Cucumber', '10']
        ]
        assert.deepEqual(table.rows(), expected)
      })
      """
    When I run cucumber-js
    Then it passes
* hashes: returns an array of objects where each row is converted to an object (column header is the key)
* rows: returns the table as a 2-D array, without the first row
  • without column header
 Scenario: raw
    Given a file named "features/passing_steps.feature" with:
      """
      Feature: a feature
        Scenario: a scenario
          Given a table step
            | Cucumber     | Cucumis sativus |
            | Burr Gherkin | Cucumis anguria |
      """
    Given a file named "features/step_definitions/passing_steps.js" with:
      """
      import {Given} from 'cucumber'
      import assert from 'assert'
      Given(/^a table step$/, function(table) {
        const expected = [
          ['Cucumber', 'Cucumis sativus'],
          ['Burr Gherkin', 'Cucumis anguria']
        ]
        assert.deepEqual(table.raw(), expected)
      })
      """
    When I run cucumber-js
    Then it passes
* raw: returns the table as a 2-D array
* rowsHash: returns an object where each row corresponds to an entry (first column is the key, second column is the value)

Attachments

文字、图片和其它类型的数据都可以通过attachments添加到时间协议和json格式的输出结果中。具体使用可以参照Attachments

API Reference

查询CucumberJS的API通过这个链接API Reference

相关文章

  • CucumberJS

    Cucumber.js是用JavaScript实现的Cucumber,可以运行在Node.js(4.0及以上版本)...

  • Debug Cucumberjs

    cucumberjs 使用的是feature文件当作test case,普通run起来的方式也是通过指令 cucu...

网友评论

      本文标题:CucumberJS

      本文链接:https://www.haomeiwen.com/subject/kvvybftx.html