在前端項目中,前端測試並無被重視,緣由有不少,好比 學習/研發成本高,團隊不夠重視,或者項目不合適等,在這裏咱們不去追究是什麼緣由致使這種現象,可是有一點我很肯定,形成這種緣由,還有一個更重要的緣由,就是 「意識不到位」,即便有不少同窗瞭解過單元測試,可是也不知道如何應用到 「項目」 中,針對這種現象,咱們從一個簡單卻很常見的小項目,來打開測試工程化
冰山一角html
在刷題的過程當中,咱們常常會使用一個項目用於練習寫筆試題,好比排序,查找之類的算法題目前端
新建一個工程,目錄以下node
├── index.js ├── index.html └── src └── search.js
search.js
和index.js
便可console.log(binarySearch([1],1)===0)
二分法查找
和順序查找
函數/** * 二分法 * @param {Array} arr */ function binarySearch(arr, expected) { let start = 0 let end = arr.length - 1 while (start <= end) { let mid = parseInt(start + (end - start) / 2) let value = arr[mid] if (value === expected) { return mid } else if (value > expected) { end = mid } else { start = mid } } return -1 } /** * 順序查找 * @param {*} arr * @param {*} expected */ function sequentialSearch(arr, expected) { let i = 0 while (i > arr.length) { let value = arr[i] if (value === expected) { return i } i++ } return -1 }
OK,大功告成,把頁面拖到瀏覽器中直接運行,連服務器都省了~~!
當我準備爲我這個完美的項目鼓掌的時候,眼角瞟到個人座右銘,成爲一個專業的大前端,此時此刻 專業這個詞格外刺眼,做爲新世紀好青年,我怎麼可能讓別人質疑個人專業,因而我要繼續裝(入)逼(坑)
git
. ├── node_modules └── test └── test.js └── src └── search.js ├── package.json ├── .gitignore ├── index.js
在 package.json 配置算法
{ .... "scripts":{ "test":"node test/test.js" } }
對應 js的模塊 要改爲commonjs
規範
search.js 調整npm
function binarySearch(){ //todo } function sequentialSearch(){ //todo } module.exports = { binarySearch, sequentialSearch }
index.js 調整json
const { binarySearch,sequentialSearch } = require('./src/search') module.exports = { binarySearch, sequentialSearch }
test.js 調整,爲了讓提示更加明顯點,咱們嘗試讓描述更加豐富點數組
const { binarySearch,sequentialSearch } = require('../index') console.log(‘二分查找: [1]的1在數組0位置上’,binarySearch([1],1)===0) console.log(‘二分查找:[1,2,3]的1在數組0位置上’,binarySearch([1,2,3],1)===0) console.log(‘二分查找:[1,2,3]的2在數組1位置上’,binarySearch([1,2,3],2)===0) console.log(‘順序查找:[1]的1在數組0位置上’,sequentialSearch([1],1)===0) console.log(‘順序查找:[1,2,3]的1在數組0位置上’,sequentialSearch([1,2,3],1)===0) console.log(‘順序查找:[1,2,3]的2在數組1位置上’,sequentialSearch([1,2,3],2)===0)
一頓操做猛如虎以後,感受完美的一筆~~
我火燒眉毛,運行 npm run test
promise
二分查找:[1]的1在數組0位置上 true 二分查找:[1,2,3]的1在數組0位置上 true 二分查找:[1,2,3]的2在數組1位置上 false 順序查找:[1]的1在數組0位置上 false 順序查找:[1,2,3]的1在數組0位置上 false 順序查找:[1,2,3]的2在數組1位置上 false
咱們發現 有幾點不足:瀏覽器
爲了解決 青銅時代 遺留下很多體驗問題,咱們不得不封裝一些方法,強化console的輸出,文檔輸出,可視化等輸出,然而咱們所作的一切強化,都是新概念 測試框架的雛形,不過在正式介紹 測試框架前,咱們先了解下 斷言
「我×,測試框架?斷言?這尼瑪又是什麼?」
斷言是單元測試中用來保證最小單元是否正常的檢測方法,用於判斷邏輯執行是否達到開發者預期的表達式,斷言在運行的過程當中,若斷言不爲真,程序會停止運行
「經常使用的斷言庫有哪些?」
咱們先簡單學習 assert, 做爲Nodejs內置核心模塊,無需引用,最爲 斷言 入門庫最爲合適
## assert
var assert=require('assert') assert.equal(Math.max(1,100),100)
一旦 assert.equal()不知足指望,將會拋出AssertionError
異常,整個程序將會中止運行
經常使用的檢測方法
「感受腦袋疼,能不能通俗點?」
先來一個例子,壓壓驚,咱們把青銅時代的代碼優化下
console.log(‘順序查找:[1]的1在數組0位置上’,sequentialSearch([1],1)===0) //爲了通用性,咱們把sequentialSearch([1],1)===0 提煉出來 function equal(actual,expected,message){ return actual===expected?message:`${actual}!==${expected}` } console.log(‘順序查找:[1]的1在數組0位置上’,equal(sequentialSearch([1],1),0,'成功'))
通俗的說 就是 equal
這個方法就是斷言
「我迷迷糊糊的貌似明白了一點,那我運行一下嚐嚐鮮吧」
test/index.js
const assert = chai.assert const { binarySearch } = require('../index') assert.equal(binarySearch([1], 1), 0)//成功 assert.equal(binarySearch([1], 1), 1)//失敗 assert.equal(binarySearch([1,2], 2), 1)//成功 assert.equal(binarySearch([1,2], 1), 0)//失敗
運行 node test/index.js
//失敗輸出 AssertionError: expected 0 to equal 1 at Object.<anonymous> (F:\learn\test\index.js:19:8)
「呃....我以爲這體驗,也青銅時代差很少」
咱們能夠看到,在第二個測試用例執行時,發現代碼執行失敗後,直接退出程序,同時提示你 指望值
和實際運行值
,以及對於錯誤代碼相關提示
等等。錯誤提示方面比封裝equire
方法強大很多;可是,依舊不能讓我願意使用它。
沒錯,斷言拿到很是重要錯誤信息;可是他沒有解決體驗問題;若是說 斷言是裏子,那測試框架 就是面子
「測試框架是什麼?」
測試框架 通俗的說就是專門 服務於代碼塊測試 的解決方案,他主要有如下功能
「經常使用的測試框架有哪些?」
通俗的說,測試框架 就是 管理/執行斷言,他和斷言一塊兒使用將會更增強大
mocha 是一款強大的測試框架,可以運行在nodejs和瀏覽器中,可以高效的管理測試用例,支持多種測試報告格式
支持兩種測試風格:TDD/BDD
經常使用方法
TDD
使用suite
pending
表示hook-用於協助describe
中測試用例的準備·安裝·卸載和回收等工做,Hook
通常用於describe
內,但也能夠describe
外,做爲頂級Hook
describe
時觸發執行describe
中每一個測試用例執行前和執行後觸發執行Full example
test/index.js
describe('hooks', function() { before(function() { console.log('before') }); after(function() { console.log('after') }); beforeEach(function() { console.log('beforeEach') }); afterEach(function() { console.log('afterEach') }); it('Test1',()=>{ console.log('test1') }) it('Test2',()=>{ console.log('test2') }) // test cases });
運行 npm run test
{ "script":{ " test":"mocha" } }
hooks
before
beforeEach
test1
√ Test1
afterEach
beforeEach
test2
1) Test2
afterEach
after
1 passing (15ms)
1 failing
1) hooks
Test2: AssertionError: expected 0 to equal 1 + expected - actual -0 +1 at Context.it (test\index.js:93:12)
咱們能夠看到 基於mocha後的斷言,他的提示體驗大大的提高 - 成功後,有相關提示 - 遇到失敗時,依舊能夠執行下去,展現全部失敗用例信息 - 統計測試用例成功數和失敗數 4. **異步處理** - done
it('should save without error', (done)=> { var user = new User('Luna'); user.save((err)=> { if (err) done(err); else done(); }); //user.save(done); }); ``` - promise ```ts it('respond with matching records', ()=> { return db.find({type: 'User'}).should.eventually.have.length(3); }); ``` - async/await ```ts it('responds with matching records', async function() { const users = await db.find({type: 'User'}); users.should.have.length(3); }); ```
Only-屏蔽其餘測試單元/測試用例,只執行標識爲Only的測試單元/用例。通常用於 當你的單元測試越寫越多時,只想測試新寫的單元測試是否正確,這個屬性就能夠幫你在執行時,幫你過濾掉其餘測試,加快執行速度
describe.only('something', function() { // 只會跑包在裏面的測試 })
或者
it.only('do do', () => { // 只會跑這一個測試 })
skip-表示執行時,跳過標識的測試單元/測試用例,能夠做用於describe
和it
it.skip('should return -1 unless present', function() { // 代碼不存被執行 }); it('should return the index when present', function() { // 代碼會執行 });
能夠this.skip()
在測試用例執行的時候,根據運行時過濾當前測試案例
describe('outer', function() { before(function() { this.skip(); }); after(function() { // will be executed }); describe('inner', function() { before(function() { // will be skipped }); after(function() { // will be skipped }); }); });