What is Test Cafe
TestCafe is a node.js tool to automate end-to-end web testing, you can write tests in JS or TypeScript, run them and view results.
简言之, Testcafe就是一个可以自动化前端end-to-end测试的工具,我们可以使用简单的JS或者Typescript写测试用例。
Installation
preparation
需要提前安装NodeJS, 官网没有指定版本,本文基于NodeJS 8+撰写。
Install TestCafe
- Globally
npm install -g testcafe
- Locally
npm install --save-dev testcafe
建议使用本地安装,这样团队里其他人直接npm install
便可安装相同版本的所有依赖。
How to run test cases
Command Line Interface
可以使用命令行执行单元测试
- 使用指定浏览器
testcafe chrome tests.js
testcafe path:/safari.app tests.js
- 使用所有安装的浏览器
testcafe all tests.js
- headless mode
Chrome 和 Firefox 支持 headless modetestcafe "chrome:headless" tests.js
更多信息请参考 Command Line Interface
Programming Interface
也可以写JS代码用Node执行单元测试,这也是本文着重推荐的方法,因为这个方式更加灵活。
- 引入工厂函数
const createTestCafe = require('testcafe')
使用工厂函数获得TestCafe实例
工厂函数接受三个参数, 分别是 host controlPanelPort servicePort,返回一个promise, 该promise的最终结果便是一个TestCafe实例createTestCafe('localhost', 1337, 1338) .then(testcafe => { /* ... */ });
TestCafe对外暴露三个方法,分别是:
createBrowserConnection
createRunner
close
,详情请参考 TestCafe Class调用
createRunner
testcafe.createRunner
返回一个Runner实例,该实例对外暴露多个方法,用于配置和执行测试任务,支持链式调用,比如:const runner = testcafe.createRunner(); return runner .src(['test1.js', 'test2.js']) // 可以提前定义一个数组,或者将需要执行的文件保存在一个文件里,更加灵活,也可以配置文件夹 .filter((testName, fixtureName, fixturePath) => { //Add some filters based on testName, fixtureName, fixturePath }) .browsers(["chrome:headless"]) .reporter('json', stream) // stream is the report file, like const stream = fs.createWriteStream('report.json'); .run({ selectorTimeout: 10000, // the timeout testcafe wait for an element to appear skipJsErrors: true // to ignore JS error });
详情请参考 Runner Class
How to write test cases
Code Structure
Fixture
TestCafe使用fixture来组织测试用例,一个测试文件必须包含一个或多个fixture
fixture(fixtureName)
fixture `fixtureName`
可以指定fixture的开始页面:
fixture.page(url)
fixture.page `url`
Test Case
然后写测试用例
test
.page `url`
(testName, async t=> {
/* Test Code */
})
注意传入的参数t,它是 test controller,包含测试API和测试用例上下文,使用它我们可以调用 test actions, 处理浏览器对话框,等待,执行断言。
Make Test Step Common
也许你会注意到 t 是在测试用例中拿到的, 如果我们需要把一个公用的action抽出来,如何获得 t 呢?
TestCafe提供了一种直接引入t的方式,此时t不包含具体测试用例的上下文,但包含了测试API, 比如:
async login() {
await t
.typeText("#user", "name")
.typeText("#pwd", "pwd")
.click("#login")
}
看到这里,也许你对typeText
click
很陌生,没关系,后面会提到。
Test Hooks
Test Hooks, 执行在Test Case之前或之后
fixture.beforeEach(fn(t))
fixture.afterEach(fn(t))
test.before(fn(t))
test.after(fn(t))
注意 test.before
test.after
会覆盖fixture.beforeEach
fixture.afterEach
, Test Hooks 同样会拿到Test Controller实例。
Skip Tests
可以跳过某些test case 或者fixture
fixture.skip
test.skip
也可以指定只执行某些test case或fixture
fixture.only
test.only
Selectors
请参考Selectors
Actions
请参考Actions
Assertions
Assertion | Description |
---|---|
eql | deep equal |
notEql | not deep equal |
ok | actual is true |
notOk | actual is false |
contains | Array or String or Object or promise contains |
notContains | Array or String or Object or promise not contains |
typeOf | type check |
notTypeOf | type check |
gt | Greater than |
gte | greater than or equal to |
lt | less than |
lte | less than or equal to |
within | range from start and finish |
notWithin | not range from start and finish |
match | regex check |
notMatch | regex check |
详情请参考Assertion API
Tricks
ClientFunction
在之前的章节我们说在 test case 中, 我们可以执行 test controller 对外暴露的 action, 执行断言,获取上下文变量等等,但是关于 client side 的数据却无法直接拿到,比如:
fixture("Fixture")
test('window', async t=> {
await t.navigateTo("url");
await t.expect(window.location.href).eql("url")
})
会报出如下错误:
window is not defined
TestCafe 提供了ClientFunction构造函数,我们可以传入一个回调函数,在回调函数中可以访问 window
const getWindowLocation = ClientFunction(() => window.location)
fixture("Fixture")
test('window', async t=> {
await t.navigateTo("url");
let location = await getWindowLocation();
await t.expect(location.href).eql("url")
})
Role
在很多网站中,具有不同角色的用户可以访问不同的界面或功能,TestCafe 提供了Role
构造方法并且在 TestController 中暴露 UseRole
方法以便切换角色。
首先引入
Role
构造函数import { Role } from 'testcafe'
创建 role
const user = Role(Env.LOGIN_URL, async t => { await t .typeText("userInput", "name") .typeText("pwdInput", "123") .click("submitBtn"); });
在 test case 中切换 role
t.useRole(user)
How to debug
笔者认为TestCafe的调试功能不太成熟,只支持下一步等简单操作
t.debug()