[TOC]
单元测试
目的:单元测试能够让开发者明确知道代码结构
原则:单一职责、接口抽离、层次分离
断言库:保证最小单元是否正常运行检测方法
测试风格:测试驱动开发(Test-Driven Development,TDD),行为驱动开发(Behavior Driver Development,BDD),均是敏捷开发开发方法论。
- TDD 关注所有功能十分被实现(每个功能必须有对应的测试用例),suite配合test利用assert('tobi' == user.name),即在开发前,有测试人员或其他人员将所有功能的测试用例编写完成,评审通过后,再按照测试用例进行开发,这种对于测试用例是相当有导向性的
- BDD关注整体行为是否符合整体预期,编写的每一行代码都要目的提供一个全面的测试用例集。expect/should,describe配合it利用自然语言expect(1).toEqual(fn())执行结果,即开发完成后再编写测试用例。
单元测试框架
- better-assert(TDD断言库)
- should.js、expect.js、Jasmine.js(BDD断言库)
- Node本身集成的assert断言库
- chai.js(TDD和BDD双模)
单元测试运行流程
before -> before -> it -> after -> afterEach
每个测试用例组通过describe进行设置
- before每个测试用例(it)开始前
- beforeEach 每个测试用例开始前
- it定义测试用例并利用断言库进行设置chai如:expect(x).to.equal(true); 异步mocha
- 以上专业术语叫mock
karma的使用
- 安装全局karma脚手架
npm install -g karma-cli
首先在我们的项目中
使用命令
npm install karma --save-dev
- 还需要安装
npm install karma-jasmine jasmine-core --save-dev
先说一下这俩个包,karma-jasmine和jasmine-core是一对的,当我们有什么karma-pack 后面就要安装pack-core,是一对的,不能分开的
说明
自动化单元测试
karma自动化runner集成PhantomJS无刷新
npm install -g karma
npm install karma-cli --save-dev
npm install karma-chrome-launcher --save-dev
npm install karma-phantomjs-launcher --save-dev // 安装无头浏览器
npm install karma-mocha --save-dev
npm install karma-chai --save-dev
这里还需要注意一个问题,因为我们这里是使用无头浏览器
所以我们需要安装一个无头浏览器 , 需要哪个无头浏览器就安装哪个无头浏览器
npm install karma-phantomjs-launcher --save-dev
e2e测试
由于现在nodejs可以驱动硬件的插件
插件selenium-webdriver
在测试文件夹下新建e2e/index.js
// e2e/index.js
const { Builder, By, Key, until } = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('firefox').build();
try {
await driver.get('http://www.baidu.com');
await driver.findElement(By.name('wq')).sendKeys('测试', Key.RETURN);
await driver.wait(until.titleIs('测试_百度搜索'), 1000);//Key.RETURN 绑定回车事件
} finally {
// 浏览器退出
await driver.quit();
}
})();
这里还需要安装一个插件 , 我们打开npmjs的selenium-webdriver插件页面
进入fireFox插件下载页面下载完成后
将压缩包放到项目根目录下
然后在packag.json里面添加一个e2e脚本
"scripts": {
...,
"e2e": "node ./test/e2e/index.js",
.....
}
然后使用命令npm run e2e , 他会自动打开浏览器执行我们上面写的脚本
有哪些selenium-webdriver有很多API , 具体api在官网上
selenium-webdriver官网 https://selenium.dev/documentation/en/getting_started_with_webdriver/locating_elements/
提示 : 如果测试不通过他会显示
请求超时提示 , 表示返回的结果和预期不一样
以上就是e2e测试的基本用法
UI测试
这里介绍一个关于无头浏览器的一个配对css测试库 phantomcss , 但是这里不使用这个库
- 我们使用另外一个库backstopjs
首先安装
npm install -g backstopjs // 全局
npm install backstopjs --save-dev // 建议安装本项目
添加运行命令 , 并运行命令
"scripts": {
...,
"bsinit": "backstop init",
.....
}
-
运行完bsinit命令后就会生成一个json文件和一个backstop_data文件
UI测试框架目录介绍
├── backstop_data
│ └── bitmaps_reference //存储样板图的地方
│ └── bitmaps_test //截图存储的地方
│ └── engine_scripts //配置静态服务器,自定义脚本casper/puppet/chromy
│ └──clickAndHoverHelper
│ └──loadCookies
│ └──onBefore
│ └──onReady
│ └──waitForHelperHelper
│ └── html_report //执行test后弹出的html界面
├── backstop.json //backstop的配置文件
backstop.json文件解释
{
//测试用例id,用于屏幕截图命名。BackstopJS将自动为您生成一个,以避免命名与BackstopJS资源的冲突。
"id": "backstop_default",
//测试视口,就是配置各种分辨率
"viewports": [{
"label": "phone", // iphone
"width": 320,
"height": 480
},
{
"label": "phone", // iphone
"width": 750,
"height": 960
},
{
"label": "tablet", //平板
"width": 1024,
"height": 768
}
],
//在执行所有脚本前、页面加载后执行的脚本。通过他我们可以执行用express做一个静态服务器 支持casper chromy puppet
"onBeforeScript": "puppet/onBefore.js",
"onReadyScript": "puppet/onReady.js",
//测试用例
"scenarios": [{
"label": "BackstopJS Homepage", //测试名称
"cookiePath": "backstop_data/engine_scripts/cookies.json", //设置cookies
"url": "https://garris.github.io/BackstopJS/", //所测试的url
"referenceUrl": "", //创建引用时指定不同的状态或环境。
"readyEvent": "", //预定义的字符串记录到控制台来触发屏幕捕获。---实现异步交互
"readySelector": "", //等到此选择器存在后再继续 ---实现异步交互
"delay": 0, //等待几秒后
"hideSelectors": [], //设置为visibility的选择器数组:hidden
"removeSelectors": [], //设置为display的选择器数组:none
"hoverSelector": "", //满足上述条件后 - 使用此脚本修改屏幕前的UI状态镜头,例如悬停,点击等
"clickSelector": "", //在屏幕截图之前单击指定的DOM元素。
"clickSelectors": "", // *仅限Puppeteer *获取selctors数组 - 模拟多个顺序点击交互。
"postInteractionWait": 0, //在与hoverSelector或clickSelector交互后等待选择器(可选择接受以ms为单位的等待时间。想法用于单击或悬停元素转换。默认使用onReadyScript)
"selectors": [], //选择需要截图的选择器
"selectorExpansion": true, //定位元素
"expect": 0, //跟选择器配合使用,说期望找到的选择器的数量跟配置的数量是否匹配,不匹配的话表示测试失败
"misMatchThreshold": 0.1, //允许通过测试的不同像素的百分比
"requireSameDimensions": true //测试必须与参考尺寸相同
}],
"paths": {
"bitmaps_reference": "backstop_data/bitmaps_reference", //存储样板图
"bitmaps_test": "backstop_data/bitmaps_test", //截图输出路径
"engine_scripts": "backstop_data/engine_scripts", //js配置路径
"html_report": "backstop_data/html_report", //显示对比图的html
"ci_report": "backstop_data/ci_report"
},
//报告的形式,支持命令行和浏览器两种
"report": ["browser"],
"engine": "casper", //配置引擎属性,slimerjs(Gecko / Mozilla,需要安装),casper,chromy(webkit)
"engineOptions": { //配置引擎属性的默认值
"casperFlags": [
"--engine=slimerjs",
"--proxy-type=http",
"--proxy=proxyIp:port",
"--proxy-auth=user:pass"
]
},
"asyncCaptureLimit": 5, //一次能捕获5个屏幕
"asyncCompareLimit": 50, //配置测试期间所需的RAM量
//是否打印测试日志
"debug": false,
"debugWindow": false,
"resembleOutputOptions": { //比较差异输出图片的配置
"errorColor": {
"red": 255,
"green": 0,
"blue": 255
},
"errorType": "movement",
"transparency": 0.3,
"ignoreAntialiasing": true
}
}
- 然后继续添加脚本命令
"scripts": {
...,
"bsui": "backstop test",
.....
}
-
然后修改backstop.json文件
-
这里添加我们的所需要测试机型的宽高 , iphone和tablet是ipad端的意思
-
所需的cookie和所需测试的url地址
所需要测试的图片下面就是backstop从我们工程截图下来用作比对的图片 , 是backstop工具自己截图的
其他就不细说了
node端的测试
- 这里使用mocha测试和mochawesome做测试图表 , 具体的配置可查看npm官网 https://www.npmjs.com/package/mochawesome
安装好这两个npm包后 , 我们在根目录下新建一个文件mochaRunner.js ,
// mochaRunner.js
const Mocha = require('mocha')
const mocha = new Mocha({
reporter: 'mochawesome',
reporterOptions: {
// reportFilename: 'customReportFilename',
reportDir: 'doc/custom-report', // 用来存放
// quiet: true
}
});
mocha.addFile('./test/service/router.spec.js'); // 这是我们需要测试的文件
mocha.run(function () {
process.exit();
})
- 然后在test目录下新建service -> app.js和service -> router.spec.js , 代码如下
// app.js 一个简单的http服务
const express = require('express')
const app = express();
app.get('/', function(req, res){
res.send({
data: '123'
})
res.end()
})
const listen = app.listen(3000, function(){
console.log('listen 3000');
})
module.exports = app
- 编写测试代码
// router.spec.js
const superagant = require('supertest');
const app = require('./app');
function request() {
return superagant(app.listen());
}
describe('node接口測試',function(){
it('接口测试', function (done) {
request()
.get('/')
.expect(200)
.expect("Content-Type", /json/)
.end(function (err, res) {
if(err) done(err)
if(res.body.data === '123'){
console.log(res,'res');
done()
}else{
done(new Error('接口数据异常'))
}
})
})
})
- 然后在package.json添加脚本文件 , 运行命令 , 即可
"scripts": {
...,
"service": "node ./mochaRunner.js",
.....
}
总结 : 当然以上都是一些非常简单且相对比较繁琐的工作 , 一般工程是不会做这种工作的 , 因为这样的编码速度太低了
我们工程真正做e2e的时候工程一般使用 night watch , 为了避免工程太大 , 这样写e2e编码任务过于繁重 , 我们一般会做一下ui的记录 UI自动录入 , 让QA工程师点 , 点完自动生成测试脚本 , 使用阿里巴巴的f2etest
包括jest
rize.js( 替代了phantomJS , phantomJS已经停止更新了 , 由rize.js一统江山了)