使用Testcafe搭建一个前端自动化测试框架,要如何开始,需要用到Testcafe的哪些知识
1. 准备开发环境:安装nodeJS 以及 Testcafe
node init
node install testcafe
2. 基本配置文件:新建一个testcaferc.json
在这个配置文件中,定义了当失败时截图的保存规则,
skipJsErros
让Testcafe忽略测试网页上发生的Javascript错误。
selectorTimeout
指定Testcafe等待一个页面元素的时间,超过这个时间就会报错。
pageLoadTimeout
指定Testcafe等待一个网页加载完成的时间,超过这个时间就会开始测试。
assertionTimeout
指定Testcafe等待一个断言通过的时间,超过这个时间就会报错。
{
"screenshots":{
"path": "./screenshots",
"takeOnFails": true,
"pathPattern": "${DATE}_${TIME}/${USERAGENT}/${TEST_ID}.png",
"fullPage": true
},
"skipJsErrors": true,
"selectorTimeout": 50000,
"pageLoadTimeout": 10000,
"assertionTimeout": 20000
}
3. 使用PageObject模式搭建
新建文件夹,名为pages,存放页面对象模型类
新建文件夹,名为tests,创建测试脚本
4. 在pages文件夹下写页面抽象类
以登录页面为例,封装页面类 login,构造器内初始化用户名,密码和登录按钮的定位方式。定义login方法,供外部调用。
export default class login{
constructor() {
this.userNameInput = Selector("#userName");
this.passwordInput = Selector("#password");
this.loginButton = Selector("#login");
}
async login(userName, password){
await t
.typeText(this.userNameInput, userName)
.typeText(this.passwordInput, password)
.click(this.loginButton)
}
}
以导航栏为例,一般来说,我们会对导航栏单独定义页面对象类。
export defalut class Navigation{
constructor(){
const a = Selector('a');
this.homePage = a.withText('Home');
this.settingPage = a.withText('settings');
}
}
5. 对登录页面使用Role,适应登录不同环境
在Testcafe中,可以使用Role来切换不同的角色。Testcafe会自动保存和恢复Role的认证数据,提高测试效率和灵活性。
Role的生命过程包括:创建、激活、注销。
Role的优点:
- 只执行一次登录过程,缓存和重用认证数据。
- 可以在多个网站之间共享认证数据。
- 可以自动导航到登录页面和返回页面。
- 可以通过preserveUrl选项来保留登录后的页面。
const userSIT = Role(
`url`,
async () => {
const userName = process.env['USERNAME'];
const password = process.env['PASSWORD'];
const page_login = new Login();
aswit page_login.login(userName, password);
)
6. 试写一个测试用例
const navigation = new Navigation();
fixture `access settings page`.beforeEach(async() => {
await t.userRole(userSIT).navigateTo(url);
});
test('access setting page', async () => {
await t.click(navigation.setting);
}
)
断言一般用哪些方法
# 判断元素文本是否符合预期
await t.expect(element.innerText).eql('result');
# 判断元素值是否符合预期
await t.expect(element.value).eql('result');
# 判断按钮是否存在
await t.expect(this.editBtn.exists).ok();
# 判断元素是否具有该属性
await t.expect(this.editBtn.hasAttribute('disabled'));
# 用包含方法来做模糊查询
await t.expect(getLocation()).contains('heading');
选择元素的常用方法
Selector('.className').filterVisible().withAttribute(value, '111');
Selector('.className').filterVisible().withText();
Selecotr('.className').nth(0).value;
t.typeText(element, value, {replace: true})
const getLocation = ClientFunction(()=> document.location.href));
7. 配置package.json文件
"scripts":{
"run_e2e_local": "testcafe chrome ./src/tests --reporter html:report/report.html",
"run_e2e_docker": "testcafe chromium:headless,firefox:headless ./src/tests --reporter html:report/report.html"
}