Hooks(钩子)
Hooks(钩子) 用于在每个场景之前和之后设置和清理环境。有关传递给Hooks的第一个参数的规范,请参阅 API参考。 如果定义了多个Before hooks,会按它们被定义的顺序执行。多个 After hooks 按照它们被定义的相反顺序执行。
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 可以根据场景的标签有条件地选择执行。
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
// 同步
Before(function() {
// 执行某些运行时检查,以决定是否跳过当前的场景
return 'skipped'
});
BeforeAll / AfterAll
如果您需要在所有场景之前或之后完成一些设置/清除工作,请使用BeforeAll
/ AfterAll
。像hooks和步骤一样,这些可以是同步的、接受回调函数或返回一个Promise。
不同于Before
/ After
,这些方法不会有world实例,即this
指针指向的对象。虽然每个场景都有自己的world实例,BeforeAll
/ AfterAll
hooks在所有场景之前/之后运行,因此没有world实例。
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是BeforeAll
、AfterAll
、Before
和After
:
BeforeAll
: 启动被测应用、最小化CukeTest、生成模拟数据等环境配置或准备工作;AfterAll
: 关闭被测应用、恢复CukeTest、删除测试数据等清理工作;Before
和After
: 场景间间隔、场景开始/结束时截图、在报告中附上测试数据等每个场景都需要执行的工作。JavaScriptconst {BeforeAll, AfterAll, Before, After} = require('cucumber')
上述方法可以通过拖拽工具箱->Cucumber中的
BeforeAll
、AfterAll
、Before
和After
方法块到脚本编辑器中来自动的引入。Hooks只能在脚本中维护,因此对于阅读剧本来了解测试过程的业务人员来说,有时会带来困惑。因此Hooks中最好不要涉及业务过程,或者说应该保证业务过程都维护在剧本和步骤中。
以上除了引用BeforeAll
、AfterAll
、Before
、After
钩子函数外,还引入了设置步骤默认超时时间的函数setDefaultTimeout()
来设置超时时间,通常项目中默认会在support/env.js
文件中自行设定,缺省值为5秒具体可以查阅超时时间。
常见的桌面自动化Hooks
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');