欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用TestCafe进行UI测试

程序员文章站 2024-03-18 11:30:52
...


Cypress,TestCafe,Puppeteer被誉为后Selenium时代的Web UI自动化测试的三驾马车,本文是对其中之一的TestCafe的使用进行简要概述,会以实际的例子带你一起搭建一个五脏俱全的UI测试Demo。

TestCafe简介

关注到TestCafe是由ThoughtWorks发布的技术雷达,2018年11月TestCafe首次进入技术雷达,处于评估阶段,2019年4月的技术雷达里,它的状态更新为试验阶段。TestCadfe的官网描述的特点有以下几点:
1.自动等待:页面加载、执行动作后自动等待元素出现,无需手动设置
2.测试脚本支持javaScript&typeScript
3.可以识别被测页面的js语法错误
4.支持同时打开多个浏览器页面并行执行用例
5.有强大易读的API供使用者使用
6.支持持续集成
7.Live模式方便调试用例
以上几点会在下面一一详细讲解。

安装TestCafe并运行官网Demo

1.安装TestCafe

(1)打开电脑命令行执行以下命令

npm install -g testcafe

(2)安装完成可以执行以下命令查看testCafe版本

testcafe —version

2.运行官网Demo

(1)从官网下载示例代码:https://devexpress.github.io/testcafe/downloads/sample-test.zip
(2)将该zip包里的两个js文件copy到你自定义的任意目录下,用VSCode打开这两文件,可以看见test-example.js是测试用例,basic-page-model.js是page object
(3)然后从命令行进入该目录,执行以下命令运行测试用例

 testcafe chrome test-example.js

用例执行失败,并且打印出了报告,可以看到是15行expect出错,分析用例可知,输入的是P.Parker,expect的却是Peter
使用TestCafe进行UI测试
(4)修改test-example.js第15行的Peter为Parker,再次执行用例,用例执行成功
使用TestCafe进行UI测试

新建一个项目使用TestCafe进行UI测试

以上的操作均在命令行之心,并且用例也只是一个js文件,在真实项目中,我们会创建一个项目来管理UI测试的测试用例,下面将会详细讲解如何新建一个项目然后使用TestCafe进行UI测试。

1.新建一个前端项目

(1)在自定义的任意目录下执行

mkdir testCafeProject

(2)进入testCafeProject所在目录执行

npm int

使用TestCafe进行UI测试
(3)使用IntelliJ打开该项目,使用pageObject的形式组织代码,所以新建目录page&test

使用TestCafe进行UI测试

(4)安装testCafe(如果之前已经执行过npm install -g testcafe则跳过此步骤)

npm install testcafe —save-dev

2.写测试用例

然后我们开始写测试用例,我的思路将页面元素以及执行动作都放在page里面,包成方法供测试用例使用,册书用例里面只需要调用包好方法即可,这样测试用例更加明晰,和官网的例子有些不同。以新浪微博注册为例,测试代码如下
weiboSignUpTest.js

import WeiboHomePage from '../page/weiboHomePage';//引用pageObject里的方法
import WeiboSignUpPage from '../page/weiboSignUpPage';

fixture`weibo sign up fixture`//固定写法,fixture相当于测试集,里面可以包含多个test
    .page`https://weibo.com/`;

//测试用例
test('search something in weibo and sign up test', async t => { //固定写法
    await WeiboHomePage.searchSomething('人民日报')//调用WeiboHomePage里面的方法
    await WeiboHomePage.clickSignUp()
    await WeiboSignUpPage.fillSignUpFormAndSubmit('123', '123098', '1995', '2', '20', '123')
    await WeiboSignUpPage.shouldShowErrorMessage('手机号长度11位,以13/14/15/16/17/18/19开头')
});

weiboHomePage.js

import {Selector, t} from 'testcafe'

class WeiboHomePage {

    get inputSearchContent() {
        return Selector('input[node-type=searchInput]')//使用selector选择页面元素
    }

    get signUp() {
        return Selector('.S_txt1').withText('注册')
    }

    async searchSomething(keyword) {
        await t.selectText(this.inputSearchContent).pressKey('delete')//调用testcafe的api进行页面操作,各种具体操作可以查看官网Docs->Test API
            .typeText(this.inputSearchContent, keyword).pressKey('enter')
    }

    async clickSignUp() {
        await t.click(this.signUp)
    }
}

export default new WeiboHomePage()//供其他js文件调用

weiboSignUpPage.js

import {Selector, t} from 'testcafe'

class WeiboSignUpPage {

    get telNumber() {
        return Selector('input[name=username]')
    }

    get password() {
        return Selector('input[name=passwd]')
    }

    get birthdayYear() {
        return Selector('select[node-type=birthday_year]')
    }

    get birthdayMonth() {
        return Selector('select[node-type=birthday_month]')
    }

    get birthdayDay() {
        return Selector('select[node-type=birthday_day]')
    }

    get pincode() {
        return Selector('input[name=pincode]')
    }

    get submit() {
        return Selector('a[action-type=btn_submit]')
    }

    async fillSignUpFormAndSubmit(telNumber, passwd, birthdayYear, birthdayMonth, birthdayDay, pincode) {
        await t.typeText(this.telNumber, telNumber)
            .typeText(this.password, passwd)
            .click(this.birthdayYear)
            .click(Selector('option').filter('[value="' + birthdayYear + '"]'))
            .click(this.birthdayMonth)
            .click(Selector('option').filter('[value="' + birthdayMonth + '"]'))
            .click(this.birthdayDay)
            .click(Selector('option').filter('[value="' + birthdayDay + '"]'))
            .typeText(this.pincode, pincode)
            .click(this.submit)
    }

    async shouldShowErrorMessage(errorMessage) {
        await t.expect(Selector('.error').nth(0).textContent).contains(errorMessage)
    }
}

export default new WeiboSignUpPage()

3.运行测试用例

(1)直接使用命令运行用例

testcafe chrome test/weiboSignUpTest.js

(2)将命令下载package.json里面,命令行直接运行

npm run weiboSignUpTest
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "testCafeFeedbackTest": "testcafe chrome test/testCafeFeedbackTest.js",
  "weiboSignUpTest": "testcafe chrome test/weiboSignUpTest.js"
}

4.Live模式

在写测试代码的过程中,你有没有发现这样一个问题:一旦元素找错了或者代码中有错误,用例运行失败,浏览器关闭,没办法查看现场,修改代码之后又需要重新运行用例,很耗费时间且不方便排查错误。
这时候我们就需要使用Live模式了,运行用例的时候启用Live模式:testcafe chrome test/weiboSignUpTest.js
这时候你会发现,当用例运行完成(失败/成功)浏览器并不会关闭,你可以清晰的知道用例停在哪一步了,并且可以打开developer tool进行问题排查。当你发现问题并修改代码后,testcafe会监听到代码变化,会自动重新运行用例,但在调试的过程中我发现并不是每一次它都正确监听到了代码的变化并自动重新运行用例,这时候你就需要用到一下几个命令了:
‘Ctrl+S’ - 停止运行用例;
‘Ctrl+R’ - 重新运行用例;
‘Ctrl+W’ - 监听/不监听源码的变化;
‘Ctrl+C’ - 停止live模式并且关闭浏览器.

5.多浏览器运行用例

testcafe最大的最吸引人的特点就是支持多浏览器运行用例,可以很好支持兼容性测试,也可以支持多用例并行测试减少用例运行时间。
(1)通用浏览器
同一用例多个浏览器同时运行

testcafe chrome,safari,firefox test/weiboSignUpTest.js

多个js文件里的多个用例在同一浏览器并发运行

testcafe -c 3 chrome  test/*.js

单个js文件里的多个用例在同一浏览器并发运行

testcafe -c 2 chrome test/testCafeFeedbackTest.js

(2)不常见浏览器
testcafe现在支持主流的大部分浏览器:
Google Chrome: Stable, Beta, Dev and Canary
Internet Explorer (11+)
Microsoft Edge (legacy and Chromium-based)
Mozilla Firefox
Safari
Google Chrome mobile
Safari mobile
其他暂不支持的浏览器可以自己写一个browser provider plugin,testcafe官网有详细教程可以参考:https://devexpress.github.io/testcafe/documentation/extending-testcafe/browser-provider-plugin/
在npm也有一些写好的插件,可以直接下载使用:https://www.npmjs.com/search?q=testcafe-browser-provider

6.远程设备运行测试用例

testcafe还支持在没有安装testcafe的远程设备上运行测试用例,是通过命令生成url,远程设备只要访问该url即可运行测试用例,当然,前提是远程设备需要和生成url的设备在子同一局域网内。
(1)生成二维码供远程设备访问

testcafe remote tests/weiboSignUpTest.js

(2)生成二维码供移动端访问

testcafe remote tests/weiboSignUpTest.js --qr-code

(3)如果想要多台远程设备同时连接

testcafe remote:3 tests/weiboSignUpTest.js

7.配置configure文件

由以上的练习我们可以知道,每次运行需要用例的时候需要使用各种参数来达到不同的目的,比如每次都需要指定测试运行的浏览器,浏览器是否可以在某个地方统一配置?如果要生成测试报告、截图是要怎么配置?
testcafe提供了配置文件.testcaferc.json来存储这些配置,每次运行时会使用该文件里的配置,如果运行时指定了特定参数会覆盖文件里的配置。下面会介绍几个常见的配置。
(1)指定浏览器

"browsers": ["chrome", "firefox","safari”]

在这里设置之后,运行用例的命令里就不再需要指定浏览器了,可以直接运行:testcafe tests/weiboSignUpTest.js

(2)截图相关配置

"screenshots": {
  "path": "screenshots",
  "takeOnFails": true,
  "pathPattern": "${DATE}_${TIME}/test-${TEST_INDEX}/${USERAGENT}/${FILE_INDEX}.png",
  "fullPage": true
}

(3)报告相关配置
testcafe支持多种格式的报告,内置的有spec/list/minimal/xUnit/JSON(可以各自试一下查看一下报告效果),如果想要其他格式的可以自定义格式,下载插件generator-testcafe-reporter,然后按照官网教程开发自定义报告式:https://devexpress.github.io/testcafe/documentation/extending-testcafe/reporter-plugin/,当然npm社区也有一些已经开发好的报告格式,可以自行下载:https://www.npmjs.com/search?q=testcafe-reporter。既然testcafe支持多种格式的测试报告,当然它也支持同时生成多种格式的报告,但是它只支持一种报告输出到日志中,其他类型的测试报告需要指定输出文件,如下图,配置了默认的spec类型的测试报告和html类型的测试报告并且指定输出路径。

"reporter": [
  {
    "name": "spec"
  },
  {
    "name": "html",
    "output": "report/report.html"
  }
]

(4)跳过js错误检查
testcafe有一个很棒的小功能,可以检查被测页面的js错误,如果有错误则判定为用例失败。但如果你的项目组对js错误没有很高的要求,那么你可以设置不检查页面的js错误。

"skipJsErrors": true

以上是笔者认为比较常用的configure配置,还有很多其他的有用的配置可以参考:https://devexpress.github.io/testcafe/documentation/using-testcafe/configuration-file.html

至此,使用testcafe进行UI测试常用的、特色的功能已经介绍得差不多了,当然还有持续集成部分笔者没有介绍,如果需要请参考:https://devexpress.github.io/testcafe/documentation/continuous-integration/