Hooks(钩子)

Hooks(钩子) 用于在每个场景之前和之后设置和清理环境。有关传递给Hooks的第一个参数的规范,请参阅 API参考。 如果定义了多个Before hooks,会按它们被定义的顺序执行。多个 After hooks 按照它们被定义的相反顺序执行。

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

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

// 异步回调
Before(function (testCase, callback) {
  let world = this;
  tmp.dir({unsafeCleanup: true}, function(error, dir) {
    if (error) {
      callback(error);
    } else {
      world.tmpDir = dir;
      callback();
    }
  });
});

//异步Promise
After(function () {
  // 假设 this.driver 是 selenium webdriver 实例
  return this.driver.quit();
});

标记的 hooks

Hooks 可以根据场景的标签有条件地选择执行。

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

Before(function () {
  //该hook会在所有场景之前执行
});

Before({tags: "@foo"}, function () {
  //该hook在使用@foo标记的场景之前执行
});

Before({tags: "@foo and @bar"}, function () {
  //这个hook将在使用@foo和@bar标记的场景之前执行
});

Before({tags: "@foo or @bar"}, function () {
  //这个钩子将在使用@foo或@bar标记的场景之前执行
});

//只有在指定标签时才可以使用下面的简写形式
Before("@foo", function () {
  //这个钩子将在使用@foo标记的场景之前执行
});

查看更多关于标签表达式的文档。

使用Before Hook跳过场景

如果你需要使用Before hook强制性地跳过测试,可以使用跳过步骤定义的任何构造来完成此操作。

这包括使用:同步返回,异步回调或异步Promise

JavaScript
// 同步
Before(function() {
  // 执行某些运行时检查,以决定是否跳过当前的场景
  return 'skipped'
});

BeforeAll / AfterAll

如果您需要在所有场景之前或之后完成一些设置/清除工作,请使用BeforeAll / AfterAll。像hooks和步骤一样,这些可以是同步的、接受回调函数或返回一个Promise。

不同于Before / After,这些方法不会有world实例,即this指针指向的对象。虽然每个场景都有自己的world实例,BeforeAll / AfterAll hooks在所有场景之前/之后运行,因此没有world实例。

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

//同步
BeforeAll(function () {
  //执行一些共享设置
});

//异步回调
BeforeAll(function (callback) {
  //执行一些共享设置

  //执行回调(可选地在完成时传递出错信息)
});

//通过Promise异步
AfterAll(function () {
  //执行一些共享清理
  return Promise.resolve()
});

Hooks在桌面自动化中的应用

在其它自动化(API、Web等)中,会将Hooks统一放在项目的support/hooks.js文件中;但是在桌面自动化中,Hooks常常需要引入模型文件.tmodel,因此建议放在features/step_definitions/目录的步骤定义脚本文件中(默认名为definitions1.js),可以省去重新引入模型的步骤。

类似的setDefaultTimeout()方法也可以从support/env.js中迁移到步骤定义脚本文件中。

在桌面自动化中,常用的Hooks是BeforeAllAfterAllBeforeAfter:

  1. BeforeAll: 启动被测应用、最小化CukeTest、生成模拟数据等环境配置或准备工作;
  2. AfterAll: 关闭被测应用、恢复CukeTest、删除测试数据等清理工作;
  3. BeforeAfter: 场景间间隔、场景开始/结束时截图、在报告中附上测试数据等每个场景都需要执行的工作。
    JavaScript
    const {BeforeAll, AfterAll, Before, After} = require('cucumber')

上述方法可以通过拖拽工具箱->Cucumber中的BeforeAllAfterAllBeforeAfter方法块到脚本编辑器中来自动的引入。

Hooks只能在脚本中维护,因此对于阅读剧本来了解测试过程的业务人员来说,有时会带来困惑。因此Hooks中最好不要涉及业务过程,或者说应该保证业务过程都维护在剧本和步骤中。

以上除了引用BeforeAllAfterAllBeforeAfter钩子函数外,还引入了设置步骤默认超时时间的函数setDefaultTimeout()来设置超时时间,通常项目中默认会在support/env.js文件中自行设定,缺省值为5秒具体可以查阅超时时间

常见的桌面自动化Hooks

JavaScript
const {BeforeAll, AfterAll, Before, After, setDefaultTimeout} = require('cucumber')
const { Util } = require('leanpro.common');
const { CukeTest } = require('cuketest');

setDefaultTimeout(30 * 1000); // 避免执行超时这里设置了默认超时时间

let proc; // 外部定义被测应用的进程信息变量
BeforeAll(async function () {
    CukeTest.minimize();
    proc = Util.launchProcess('path/to/testing/application');
    await model.getApplication("application").exists(10);
})

AfterAll(async function () {
    CukeTest.restore();
    CukeTest.maximize();
    Util.stopProcess(proc); // 项目运行结束后关闭被测应用
})

After(async function () {
    let screenshot = await model.getTree("Dir_View").takeScreenshot();
    this.attach(screenshot, 'image/png');
    await Util.delay(2000);
})

如果使用的是Qt自动化,那么应该使用leanpro.qt库中的QtAuto.launchQtProcessAsync()方法来启动被测应用,因此需要将:

proc = Util.launchProcess('path/to/testing/application');

替换为:

proc = await QtAuto.launchQtProcessAsync('path/to/testing/application');

results matching ""

    No results matching ""