场景中的变量传递

由于Cucumber中,每个步骤都是独立的、相互隔离的,那么如何在步骤间传递变量呢?比如说上一个步骤中操作得到的结果,需要在下一个步骤中验证结果是否正确该怎么做呢?比起使用全局变量,其实Cucumber推荐的是另一种方法,这里就要提到一个概念——World对象,每个Hook和场景中维护着一个World对象(类似HTML中的document对象或NodeJS中的global对象)用于保存场景中的变量、函数等内容。

因此使用World对象进行步骤间的变量传递就非常简单了,在步骤中将需要传递的变量赋值给World对象,接着在同个场景的其它步骤中,取出该值即可。

并且在所有的步骤定义中,都可以使用this关键字直接访问World对象,如下:

JavaScript
Given("加号左边为1", async function () {
    this.leftValue = 1;
});

运行上述步骤后,场景中的World对象就会多出一条leftValue属性,并且值为1。

在步骤间传递变量

前文提到,如果上一个步骤中操作得到的结果,需要在下一个步骤中验证结果是否正确,这一过程如何借助World对象来实现呢? 我们定义一个简单的场景,场景中完成的是简单的加法运算,以及对运算结果的校验,如下:

# language: zh-CN
@math
功能: 数学计算
加法测试,Cucumber 3.x 样例

  场景: 简单数学计算
    假如加号左边为1
    当加号右边为1
    那么结果为2

那么代码定义如下:

JavaScript
const { Given, When, Then } = require('cucumber');
//// 你的步骤定义 /////

Given("加号左边为{int}", async function (leftSideValue) {
    this.leftValue = leftSideValue;
});

When("加号右边为{int}", async function (rightSideValue) {
    this.rightValue = rightSideValue;
});

Then("结果为{int}", async function (expectedResult) {
    actualResult = this.leftValue + this.rightValue; // 实际运算结果
    if (actualResult === expectedResult) {
        this.attach(`运算结果符合预期,为${actualResult}`);
    } else {
        throw `运算结果不符合预期,预期值为${expectedResult},实际结果为${actualResult}`;
    }
});
运行结果如下:
场景中的变量传递运行结果

在上述代码中,在前两个步骤的定义中,将要用到的变量使用World对象来传递,以便第三步中使用。除了比较操作结果外,另一种常见的情况是,在场景开始前和结束后都进行一次截图,并比较两次截图(使用工具箱中的imgCompare(img1, img2)方法),使用World对象传递截图也是非常方便的。

此外,代码中还使用了this.attach()的方法,这是World对象自带的一个方法,能够将指定内容作为 附件(Attachment) 添加到报告中,适合用于在报告中加入验证结果、测试数据、运行截图等等内容。了解更多附件相关的内容可以点击查看

在Hook中使用变量传递

在上一节中提到了,World对象不仅存在于场景中,Hook中也同样存在,因为Hook在运行时也会被当作场景或者剧本的一部分。更具体的描述是,Hook中的BeforeAfter与场景共用一个World对象,因此在这两个Hook中可以定义一些供场景使用的值。将上面的代码稍微修改以后如下:

# language: zh-CN
@math
功能: 数学计算
加法测试样例

  场景: 简单数学计算
    假如加号左边为1
    当加号右边为1
    那么结果为2
#+++++++++++++++++++++++++++++++++#
  @complex @math
  场景大纲: 混合场景
    假如加号左边为<var>
    当加号右边为<increment>
    那么结果为<result>
    例子: 
      | var | increment | result |
      | 100 | 5         | 105    |
      | 101 | 5         | 106    |
      | 0   | -10       | -10    |
#+++++++++++++++++++++++++++++++++#

JavaScript
const { Given, When, Then } = require('cucumber');

//// 你的步骤定义 /////

Given("加号左边为{int}", async function (leftSideValue) {
    this.leftValue = leftSideValue;
});

When("加号右边为{int}", async function (rightSideValue) {
    this.rightValue = rightSideValue;
});

Then("结果为{int}", async function (expectedResult) {
/*++++++++++++++++++++++++++++++++++++++++*/
    if (this.fromBeforeAll) {
        this.attach(this.fromBeforeAll);
    }
    if(this.location) {
        this.attach(this.location);
    }
/*++++++++++++++++++++++++++++++++++++++++*/
    actualResult = this.leftValue + this.rightValue;
    if (actualResult === expectedResult) {
        this.attach(`运算结果符合预期,为${actualResult}`);
    } else {
        throw `运算结果不符合预期,预期值为${expectedResult},实际结果为${actualResult}`;
    }
});
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
const { Before, BeforeAll } = require('cucumber');
Before(async function (testCase) {
    this.location = `运行位置: feature文件第${testCase.sourceLocation.line}`;
})
BeforeAll(async function () {
    this.fromBeforeAll = `这是BeforeAll Hook传递的信息`;
})
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
运行结果为:
Hook中的变量传递运行结果

这里的BeforeHook中传递的变量值为运行时场景在剧本文件中的行数,对比剧本文件也能看的出来。而场景大纲中示例表的每行数据都会被渲染为一个完整的场景,因此后面三个场景各指向一行示例表的数据。了解更多关于场景大纲示例表的内容可以点击查看

results matching ""

    No results matching ""