首先我们来看下什么是BDD,什么是TDD
测试风格:测试驱动开发(Test-Driven Development,TDD)、(Behavior Driven Development,BDD)行为驱动开发均是敏捷开发方法论。 TDD关注所有的功能是否被实现(每一个功能都必须有对应的测试用 例),suite配合test利用assert('tobi' == user.name); BDD关注整体行为是否符合整体预期,编写的每一行代码都有目的提 供一个全面的测试用例集。expect/should,describe配合it利用自然语 言expect(1).toEqual(fn())执行结果。-
接下来我们看下单元测试的运行流程
来开始一个单元测试
unit测试是把代码看成是一个个的组件。从而实现每一个组件的单独测试,测试内容主要是组件内每一个函数的返回结果是不是和期望值一样。
这里我们使用karma,官网地址为: karma: https://karma-runner.github.io/latest/index.html
安装karma:
karma-jasmine jasmine-core是断言库
npm install karma --save-dev
npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
然后执行karma init
这里会有很多步选择,我们都默认就好了,但是选择浏览器时我们选择phantomjs
做完这些操作后,会生成一个karma.conf.js
文件如下:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
// 解析所有模式的基本路径
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
// 框架的使用
frameworks: ['jasmine'],
files: [
"unit/**/*.js", // 需要被测试的文件
"unit/**/*.spec.js" // 测试文件
],
// list of files / patterns to exclude
// 要排除的文件/模式列表
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
// 在将匹配的文件提供给浏览器之前,对它们进行预处理
preprocessors: { // 哪些文件需要通过覆盖率检查
'unit/**/*.js': ['coverage']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
// 使用测试结果报告程序
reporters: ['progress','coverage'], // 进度,覆盖率(需要装karma-coverage)
coverageReporter: { // 生成的测试报表
type : 'html',
dir : 'docs/coverage/'
},
// web server port
// 测试端口号
port: 9876,
// enable / disable colors in the output (reporters and logs)
// 在输出中启用/禁用颜色(记者和日志)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
// 日志相关配置
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
// 启用/禁用监视文件并在任何文件更改时执行测试(热更新)
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'], // 选择的浏览器
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
// 持续集成模式
singleRun: true, // 使用无头浏览器这里必须设置为true
// Concurrency level
// how many browser should be started simultaneous
// 并发级别
concurrency: Infinity
})
}
我们在util文件夹中新建一个文件index.js
对其进行测试,内容如下
window.add = function (a) {
return a + 1;
}
再新建一个测试文件index.spec.js
(或indexSpec.js)
escribe("测试基本函数的api",function () {
it("+1函数的应用",function(){
expect(window.add(1)).toBe(2)
})
})
这时就可以跑执行karma start
开始测试了
到这里有一个问题,如果代码中有if,else怎么办。这时我们就需要代码覆盖率检查了。下载 karma-coverage,如果报错可能是缺了karma-phantomjs-launcher和phantomjs这两个包。在上面的配置文件中我已经进行了配置,现在直接跑就ok了。
页面测试: e2e
e2e测试是把我们的程序堪称是一个黑盒子,我不懂你内部是怎么实现的,我只负责打开浏览器,把测试内容在页面上输入一遍,看是不是我想要得到的结果。
这里我们使用selenium-webdriver
来进行e2e测试,e2e测试需要一个浏览器的执行环境,所以首先在selenium-webdriver官网上下载浏览器驱动,然后安装selenium-webdriver
在e2e文件夹中新建一个baidu.spec.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('wd')).sendKeys('webdriver', Key.RETURN); // 通过名class名为wd的input框搜索webdriver
await driver.wait(until.titleIs('webdriver_百度搜索'), 1000); // 等待1s看title是否等于webdriver_百度搜索
} finally {
await driver.quit(); // 无论是否成功,退出driver
}
})();
然后我们运行: node ./e2e/baidu.spec.js
UI测试
PhantomCSS
是一个很好的UI测试插件,但是我们这里使用backstopjs
来做演示
安装backstopjs后,我们backstop init
这时会生成一个backstop_data
文件夹,和backstop.json
文件
我们首先来看下backstop_data
文件夹结构
+-- backstop_data
+-- bitmaps_reference -- 放置ui切图的文件夹
+-- bitmaps_test -- 生成的测试图例地址
+-- engine_scripts
+-- casper -- 在无头浏览器中操作鼠标
+-- chromy
+-- puppet
+-- cookies.json -- 如果网页需要配置cookie在这里配置
再来看下backstop.json
文件配置
{
"id": "yd", // 项目名称
"viewports": [ // 设备配置项
{
"label": "phone",
"width": 375,
"height": 667
},
{
"label": "tablet",
"width": 1024,
"height": 768
}
],
"onBeforeScript": "puppet/onBefore.js", // 引擎, 在engine_scripts文件夹中
"onReadyScript": "puppet/onReady.js", // 同上
"scenarios": [ // 配置截图
{
"label": "qqmap",
"cookiePath": "backstop_data/engine_scripts/cookies.json", // cookie地址
"url": "https://map.qq.com/m/", // 要被测试页面地址
"referenceUrl": "",
"readyEvent": "",
"readySelector": "",
"delay": 0,
"hideSelectors": [],
"removeSelectors": [],
"hoverSelector": "",
"clickSelector": "",
"postInteractionWait": 0,
"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": "docs/backstop_data/html_report", // 生成报表地址
"ci_report": "docs/backstop_data/ci_report" // ci报表
},
"report": ["browser"],
"engine": "puppeteer",
"engineOptions": {
"args": ["--no-sandbox"]
},
"asyncCaptureLimit": 5,
"asyncCompareLimit": 50,
"debug": false,
"debugWindow": false
}
最后执行backstop test进行测试
接口测试
接口测试我们这里使用mocha
首先安装mocha
我们新建一个app.js
文件,对app.js文件的内容进行测试
var express = require("express");
var app = express();
app.get("/test",function(req,res){
res.send({
result:"Hello World"
})
});
var server = app.listen(3000,function(){
console.log("demo app 启动");
});
module.exports = app;
我们再创建测试文件router.spec.js
const axios = require("axios");
describe("node接口", function () {
it("test接口测试", function (done) {
axios.get('http://localhost:3000/test')
.then(function (response) {
if (response.data.result == "Hello World") {
done();
} else {
done(new Error("数据请求格式错误"));
}
})
.catch(function (error) {
done(error);
});
});
});
// 高级写法
const superagent = require("superagent");
const app = require("./app");
function request(){
return superagent(app.listen())
}
request()
.get("/test")
.expect("Content-Type",/json/)
.expect(200)
.end(function(err,res){
if(res.data == "Hello World"){
done();
}else{
done(err);
}
})
最后新建mochaRunner.js
文件如下,这里我们需要下载mochawesome
来生成报表
const Mocha = require("mocha");
const mocha = new Mocha({
reporter: 'mochawesome', // 安装mochawesome(生成报表的包)
reporterOptions:{
reportDir:"./docs/mochawesome-reporter" // 生成报表位置
}
});
mocha.addFile("./service/router.spec.js");
mocha.run(function(){
console.log("done");
process.exit(); // 退出进程,不退出会卡死
});
这时我们运行node ./mochaRunner.js
如果我们需要将上面的的一起测试,只需要: npm run unit && npm run e2e && npm run ui
就OK了
JavaScript Lint&Hint
目的:检测JavaScript代码标准 原因:JavaScript代码诡异,保证团队代码规范 lint:http://www.jslint.com/
hint: http://www.jshint.com/
搭配自动化任务管理工具完善自动化测试grunt- jshint、grunt-jslint
下面来介绍一些工程用的测试包
- nightwatchjs(vue专用)
- rize+puppeteer+rize
- 阿里的f2etest(自动化录制)
这里我们需要注意下,在f2etest中有UI recorder,这个东西会打开两个浏览器,因为有些网站像验证码每次都不一样,第二台浏览器会与第一个比较,结果相同就算成功