單元測試
目的:單元測試能夠讓開發者明確知道代碼結構
原則:單一職責、接口抽離、層次分離
斷言庫:保證最小單元是否正常運行檢測方法
測試風格:測試驅動開發(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插件頁面
TEST01.png
進入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/
提示 : 如果測試不通過他會顯示
TEST02.png
請求超時提示 , 表示返回的結果和預期不一樣
以上就是e2e測試的基本用法
UI測試
這裏介紹一個關於無頭瀏覽器的一個配對css測試庫 phantomcss , 但是這裏不使用這個庫
- 我們使用另外一個庫backstopjs
首先安裝
npm install -g backstopjs // 全局
npm install backstopjs --save-dev // 建議安裝本項目
添加運行命令 , 並運行命令
"scripts": {
...,
"bsinit": "backstop init",
.....
}
-
運行完bsinit命令後就會生成一個json文件和一個backstop_data文件
TEST03.png
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文件
TEST04.png
-
這裏添加我們的所需要測試機型的寬高 , iphone和tablet是ipad端的意思
TEST05.png
-
所需的cookie和所需測試的url地址
TEST06.png
所需要測試的圖片下面就是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一統江山了)
0人點贊