一、简介
简单说就是Node.JS编写的Web端UI自动化测试框架。官网:http://devexpress.github.io/testcafe/
与selenium使用对比
- 语言支持。selenium支持多语言(java、python、ruby、nodejs),testcafe只支持JavaScript,TypeScript
- 使用便捷性。selenium需要不同浏览器对应的webdriver版本,经常发生不兼容问题。testcafe无此担心
- 入门便捷性。相差不大
- 作为测试框架完备性。selenium需要与testng等结合使用(往往需要二次封装),testcafe不需要,本身就是一个完整的测试框架了(提供了Cases的管理,运行,失败自动重跑,错误自动截图,并发等)
- testCafe debug模式,通过代码配置或运行时设置,可以控制执行过程中失败时进入调试模式
二、快速入门
1、安装
ps:因为是Node.js 项目,前提已经装了node环境了
方法一:全局安装
npm install -g testcafe
ps: 本人在mac上安装,发现很久没成功,进而使用了局部安装
方法二:局部安装
npm install --save-dev testcafe
2、使用
step1: 编写脚本 test.js
import { Selector } from 'testcafe';
fixture `Getting Started`
.page `http://devexpress.github.io/testcafe/example`;
test('My first test', async t => {
console.log("this is case 1");
});
step2:(因为局部安装原因)找到testcafe 命令目录
sudo find / -name testcafe
结果:/Users/XXX/Documents/workspace/node_modules/.bin/testcafe
step3: 运行
/Users/XXX/Documents/workspace/node_modules/.bin/testcafe chrome YYY/testcafe/test.js
执行结果:
Running tests in:
- Chrome 70.0.3538 / Mac OS X 10.11.5
Getting Started
this is case 1
✓ My first test
1 passed (2s)
三、testcafe介绍
1、TestCafe如何组织管理测试用例
方式:fixture 和 test
描述:一个js文件可以包含多个fixture,一个fixture可以包含多个test
fixture("测试集描述")
fixture `测试集合描述`
test('用例描述',fn(t))
例如:
import { Selector } from 'testcafe';
fixture("cases manage").page("http://devexpress.github.io/testcafe/example");
test('this case 1', async I => {
console.log("this is case 1");
});
test('this case 2', async I => {
console.log("this is case 2");
});
test('this case 3', async I => {
console.log("this is case 3");
});
fixture(`cases manage 2`).page(`http://devexpress.github.io/testcafe/example`);
test('this case 1-1', async I => {
console.log("this is case 1-1");
});
test('this case 2-1', async I => {
console.log("this is case 2-1");
});
test('this case 3-1', async I => {
console.log("this is case 3-1");
});
结果:
Running tests in:
- Chrome 70.0.3538 / Mac OS X 10.11.5
cases manage
this is case 1
✓ this case 1
this is case 2
✓ this case 2
this is case 3
✓ this case 3
cases manage 2
this is case 1-1
✓ this case 1-1
this is case 2-1
✓ this case 2-1
this is case 3-1
✓ this case 3-1
6 passed (4s)
ps:每个test 执行之前都会执行fixture打开页面的操作,但只会启动一次浏览器
2、fixtrue的前置条件
fixture.beforeEach( fn(t) ):每个test执行之前都会被运行
fixture.afterEach( fn(t) ):每个test执行之后都会被运行
fixture.before(fn(t)):比beforeEach更早运行,且每个fixture只运行一次
fixture.after(fn(t)):比afterEach更晚运行,且每个fixture只运行一次
3、test的前置条件
test.before(fun(t)):该test运行之前运行
test.after(fun(t)):该test运行之后运行
test
.before(async t => {
console.log(`this is test's before`)
})
("test beforeAndafter", I => {
console.log("1111")
})
.after(async t => {
console.log(`this is test's after`)
});
test("test beforeAndafter", I => {
console.log("2222")
});
ps:test的before/after 会覆盖fixture中的beforeEach/afterEach。也就是说如果一个test里面包含了before/after 那么fixture中的beforeEach/afterEach对该test无效
4、跳过测试
fixture.skip :跳过该fixture下的所有test
test.skip : 跳过该test
fixture.only :只执行该fixture下的所有test,其余的fixture下的test全部跳过
test.only : 只运行该test,其余全部跳过
5、写测试代码
从例子中学习(以下仅仅用作演示功能使用,实际运行时需要做调整):
例子1: 页面执行动作
import { Selector } from 'testcafe';
fixture `Getting Started`
.page `http://devexpress.github.io/testcafe/example`;
test('My first test', async t => {
await t
.typeText('#developer-name', 'John Smith')
.click('#submit-button');
});
t : 测试控制器
await: 等待操作完成
例子2: 观测页面状态
import { Selector } from 'testcafe';
fixture `Getting Started`
.page `http://devexpress.github.io/testcafe/example`;
test('My first test', async t => {
await t
.typeText('#developer-name', 'John Smith')
.click('#submit-button');
const articleHeader = await Selector('.result-content').find('h1');
// Obtain the text of the article header
let headerText = await articleHeader.innerText;
});
例子3:验证
import { Selector } from 'testcafe';
fixture `Getting Started`
.page `http://devexpress.github.io/testcafe/example`;
test('My first test', async t => {
await t
.typeText('#developer-name', 'John Smith')
.click('#submit-button')
// Use the assertion to check if the actual header text is equal to the expected one
.expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');
});
更多验证:
test('Check property of element', async t => {
const developerNameInput = Selector('#developer-name');
await t
.expect(developerNameInput.value).eql('', 'input is empty')
.typeText(developerNameInput, 'Peter Parker')
.expect(developerNameInput.value).contains('Peter', 'input contains text "Peter"');
});
await t.expect(Selector('#elementId').innerText).eql('text', 'check element text', { timeout: 500 });
代码:
<div id="btn"></div>
<script>
var btn = document.getElementById('btn');
btn.addEventListener(function() {
window.setTimeout(function() {
btn.innerText = 'Loading...';
}, 100);
});
</script>
测试代码:
test('Button click', async t => {
const btn = Selector('#btn');
await t
.click(btn)
// A regular assertion fails immediately, but TestCafe retries to run DOM state
// assertions many times within the timeout until this assertion passes successfully.
// The default timeout is 3000 ms.
.expect(btn.textContent).contains('Loading...');
});
参考:
http://devexpress.github.io/testcafe/documentation/getting-started/