Mocha和單元測試

Mocha測試框架和項目實例

測試項目已上傳github

地址:https://github.com/Hanxueqing/Mocha-test

運行克隆命令,下載到本地

git clone git@github.com:Hanxueqing/Mocha-test.git

一、什么是Mocha

Mocha(發(fā)音"摩卡")誕生于2011年,是現(xiàn)在最流行的JavaScript測試框架之一,在瀏覽器和Node環(huán)境都可以使用。所謂"測試框架",就是運行測試的工具。通過它,可以為JavaScript應用添加測試,從而保證代碼的質(zhì)量。

二、Mocha安裝和準備

前期準備:安裝vue-cli腳手架、安裝node、安裝Git

(1)先用vue-cli創(chuàng)建一個vue-test項目

vue create vue-test

(2)全局安裝mocha

npm i mocha -g

將mocha安裝到本地目錄

npm i mocha -D

(3)修改package.json中的test路徑為我們本地的mocha路徑

"test": "./node_modules/mocha/bin/mocha"
image

三、測試框架

1、創(chuàng)建test文件夾

測試腳本都存放在test文件夾中

2、編寫測試框架

創(chuàng)建test/demo.js

describe("Demo", function(){
    describe("方法 1", function(){
        context("情境 1", function(){
            before(function(){
                console.log("-----測試之前------");
            });
            after(function(){
                console.log("-----測試之后------");
            });
            beforeEach(function(){
                console.log("-------每條測試之前---------");
            })
            afterEach(function(){
                console.log("-------每條測試之后---------");
            })
            it("測試 1", function(){

            })
            it("測試 2", function(){
                
            })
        })
    })
})

上面這段代碼,就是測試腳本,它可以獨立執(zhí)行。測試腳本里面應該包括一個或多個describe塊,每個describe塊應該包括一個或多個it塊。

describe

describe塊稱為"測試套件"(test suite),表示一組相關的測試。它是一個函數(shù),第一個參數(shù)是測試套件的名稱("Demo"),第二個參數(shù)是一個實際執(zhí)行的函數(shù)。

it

it塊稱為"測試用例"(test case),表示一個單獨的測試,是測試的最小單位。它也是一個函數(shù),第一個參數(shù)是測試用例的名稱("測試1"),第二個參數(shù)是一個實際執(zhí)行的函數(shù)。

測試用例的鉤子

Mocha在describe塊之中,提供測試用例的四個鉤子:before()、after()、beforeEach()afterEach()。它們會在指定時間執(zhí)行。

befor:定義測試之前進行的操作

after:定義測試之后進行的操作

beforeEach:定義每條測試之前進行的操作

afterEach:定義每條測試之后進行的操作

3、進行測試

執(zhí)行mocha命令使用全局安裝的mocha進行測試或者執(zhí)行npm test命令使用本地安裝的mocha進行測試

image

四、斷言庫chai

所謂"斷言",就是判斷源碼的實際執(zhí)行結(jié)果與預期結(jié)果是否一致,如果不一致就拋出一個錯誤。

1、全局安裝chai模塊

npm i chai -g

2、本地安裝chai模塊

npm i chai -D

3、斷言風格

斷言庫有很多種,Mocha并不限制使用哪一種。

assert風格的斷言

在test文件夾下新建test_lib文件夾,創(chuàng)建assert.js編寫測試腳本。

const chai = require("chai");
//引入斷言的風格
const assert = chai.assert;

describe("Demo", function () {
    it("使用 assert風格的斷言測試", function () {
        var value = "hello";
        //斷言value值的類型為字符串
        assert.typeOf(value, "string");
        //斷言value值等于"hello"
        assert.equal(value, "hello");
        //斷言value值的長度為5
        assert.lengthOf(value, 5);
    })
})

進入test_lib文件夾下,執(zhí)行mocha assert.js運行測試腳本,因為我們這三個斷言都是真的,所以測試通過。

image
should風格斷言

創(chuàng)建should.js編寫測試腳本。

const chai = require("chai");
const should = chai.should();

describe("Demo", () => {
    it("使用 should風格的斷言測試", function () {
        var value = "hello";
        //value應該存在
        value.should.exist
        //value的數(shù)字類型應該是一個字符串
        value.should.be.a("string");
        //value值應該等于"hello"
        value.should.equal("hello");
        //value值不等于"你好"
        value.should.not.equal("你好");
        //value的長度應該為5
                value.should.have.length(5);
        

    })
})

我們也可以換成另一種更簡潔的寫法,使用and連接斷言

value.should.exist
            .and.be.a("string")
            .and.equal("hello")
            .and.have.length(5)

進入test_lib文件夾下,執(zhí)行mocha should.js運行測試腳本,因為我們這五個斷言都是真的,所以測試通過。

image
expect風格斷言

expect斷言的優(yōu)點是很接近自然語言

創(chuàng)建expect.js編寫測試腳本。

const chai = require("chai");
const expect = chai.expect;

describe("Demo", () => {
    it("使用 expect風格的斷言測試", function () {
        var value = "hello";
        //value應該存在
        expect(value).to.exist;
        //value的數(shù)字類型應該是一個字符串
        expect(value).to.be.a("string");
        //value值應該等于"hello"
        expect(value).to.equal("hello");
        //value值不等于"你好"
        expect(value).to.not.equal("你好");
        //value的長度應該為5
        expect(value).to.have.length(5);
    })
})

進入test_lib文件夾下,執(zhí)行mocha expect.js運行測試腳本,因為我們這五個斷言都是真的,所以測試通過。

image

同樣我們也可以定義一個數(shù)字,使用expect斷言來判斷數(shù)字的區(qū)間

var number = 3;
        //判斷number是否在3~5之間的數(shù)
        expect(number).to.be.at.most(5);
        expect(number).to.be.at.least(3);
        //判斷number是否在1~3之間的數(shù)
        expect(number).to.be.within(1, 3);

五、編寫測試腳本

Mocha的作用是運行測試腳本,首先必須學會寫測試腳本。所謂"測試腳本",就是用來測試源碼的腳本。

1、測試返回結(jié)果是否正確

(1)創(chuàng)建被測試的項目lib/demo-1.js

class Demo {
    subtotal(unitPrice, quantity) {
        return unitPrice * quantity;
    }
}
module.exports = Demo;

(2)創(chuàng)建測試腳本test/demo-1.test.js

通常,測試腳本與所要測試的源碼腳本同名,但是后綴名為.test.js(表示測試)或者.spec.js(表示規(guī)格)。比如,demo-1.js的測試腳本名字就是demo-1.test.js。

//demo-1.test.js
const chai = require("chai");
const expect = chai.expect;

var Demo = require("../lib/demo-1");
var demo = new Demo();
describe("Demo",()=>{
    it("單價10塊錢的3件商品小計金額應該是30塊",function(){
        var subtotal = demo.subtotal(10,3);
        expect(subtotal).to.equal(30);
    })
})

2、異步操作測試setTimeout

(1)Mocha默認每個測試用例最多執(zhí)行2000毫秒,如果到時沒有得到結(jié)果,就報錯。對于涉及異步操作的測試用例,這個時間往往是不夠的,需要用-t--timeout參數(shù)指定超時門檻。

進入lib/demo-1.js,編寫異步等待方法,規(guī)定2秒之后返回結(jié)果

waitTwoSecond(data,callback){
        setTimeout(function(){
            callback(data);
        },2000);
    }

(2)進入test/demo-1.test.js,編寫測試腳本

//異步操作測試
    //mocha不會等到異步執(zhí)行結(jié)束以后進行測試,而是直接運行得到測試結(jié)果
    it("一段時間以后返回數(shù)據(jù)",function(done){
        demo.waitTwoSecond("hello",function(data){
            expect(data).to.equal("hello")
            done(); //只有調(diào)用done方法才能等待調(diào)用結(jié)束以后測試
            //mocha默認的等待時間是2秒,上述操作超過兩秒,報錯
            //運行命令mocha demo-1.test.js -t 5000重置等待時間解決
        })
    })

另外,上面的測試用例里面,有一個done函數(shù)。it塊執(zhí)行的時候,傳入一個done參數(shù),當測試結(jié)束的時候,必須顯式調(diào)用這個函數(shù),告訴Mocha測試結(jié)束了。否則,Mocha就無法知道,測試是否結(jié)束,會一直等到超時報錯。如果把這行刪除,則mocha不會等到異步執(zhí)行結(jié)束以后進行測試,而是直接運行得到測試結(jié)果,返回的斷言結(jié)果始終為真。

(3)雖然測試用例中規(guī)定2秒返回結(jié)果,但是實際運行時間肯定超過2秒,所以,需要用-t--timeout參數(shù),改變默認的超時設置。

mocha demo-1.test.js -t 5000

上面命令將測試的超時時限指定為5000毫秒。

3、測試接口數(shù)據(jù)https

接口地址https://douban.uieee.com/v2/movie/top250

image

(1)lib/demo-1.js

引入https模塊

var https = require("https");

定義fetchData方法

fetchData(api,callback){
        var requestUrl = `https://douban.uieee.com/v2/movie/${api}`;
        https.get(requestUrl,function(res){
            var responseData = ""
            res.setEncoding("utf8")

            res.on("data",function(chunk){
                responseData += chunk
            })

            res.on("end",function(){
                callback(JSON.parse(responseData))
            })
        })
    }

(2)test/demo-1.test.js

it("加載豆瓣api,返回的數(shù)據(jù),應該包含subjects屬性",function(done){
        demo.fetchData("top250",function(data){
            expect(data).to.have.property("subjects");
            done();
        })
    })

    it("加載豆瓣api,返回的數(shù)據(jù),subjects應為對象類型", function (done) {
        demo.fetchData("top250", function (data) {
            var subjects = data.subjects;
            expect(subjects).to.be.a("array");
            done();
        })
    })

    it("加載豆瓣api,返回的數(shù)據(jù),subjects長度應為20", function (done) {
        demo.fetchData("top250", function (data) {
            var subjects = data.subjects;
            expect(subjects).to.have.length(20);
            done();
        })
    })

    it("加載豆瓣api,返回的數(shù)據(jù),title屬性應該是字符串類型的", function (done) {
        demo.fetchData("top250", function (data) {
            var title = data.subjects[0].title
            expect(title).to.be.a("string");
            expect(title).to.equal("肖申克的救贖")
            done();
        })
    })

(3)運行結(jié)果

image

4、測試異常

(1)lib/demo-1.js

engine(fuel){
        if(fuel !== "gas"){
            throw new Error("not accept")
        }
    }

(2)test/demo-1.test.js

//定義一個異常
    it("給汽車引擎加水是不能接受的事情",function(){
        expect(function(){
            demo.engine("water");
        }).to.throw("not accept")
    })
//另外一種寫法
    it("給汽車引擎加水是不能接受的事情",function(){
        expect(demo.engine.bind(demo,"water")).to.throw("not accept")
    })

(3)測試結(jié)果

image

六、運行多個測試

1、直接使用mocha命令運行test子目錄中的測試腳本

Mocha默認運行test子目錄里面的測試腳本。所以,一般都會把測試腳本放在test目錄里面,然后執(zhí)行mocha就不需要參數(shù)了。

image

所以在控制臺中輸入mocha,只會執(zhí)行test子目錄里的測試腳本demo-1.test.js和demo.js,而test_lib中的assert.js、expect.js、should.js則不會執(zhí)行。

運行結(jié)果:

image

2、執(zhí)行test子目錄下面所有的測試用例

這時可以看到,test子目錄里面的測試腳本執(zhí)行了。但是,你打開test子目錄,會發(fā)現(xiàn)下面還有一個test/test_lib子目錄,里面還有三個測試腳本assert.js、expect.js、should.js,并沒有得到執(zhí)行。Mocha默認只執(zhí)行test子目錄下面第一層的測試用例,不會執(zhí)行更下層的用例。

為了改變這種行為,就必須加上--recursive參數(shù),這時test子目錄下面所有的測試用例,不管在哪一層,都會執(zhí)行。

mocha --recursive

運行結(jié)果:

image

3、執(zhí)行多個測試腳本

mocha命令后面緊跟測試腳本的路徑和文件名,可以指定多個測試腳本。

進入tets_lib目錄下,運行assert.js和should.js兩個測試腳本

mocha assert.js should.js

運行結(jié)果

image

七、測試用例管理

1、only表示只運行某個測試套件或測試用例。

大型項目有很多測試用例。有時,我們希望只運行其中的幾個,這時可以用only方法。describe塊和it塊都允許調(diào)用only方法,表示只運行某個測試套件或測試用例。

it.only("單價10塊錢的3件商品小計金額應該是30塊",function(){
        var subtotal = demo.subtotal(10,3);
        expect(subtotal).to.equal(30);
    })

運行結(jié)果:只運行了添加only方法的測試腳本

image

2、skip表示跳過指定的測試套件或測試用例。

it.skip("一段時間以后返回數(shù)據(jù)",function(done){
        demo.waitTwoSecond("hello",function(data){
            expect(data).to.equal("hello")
            done(); //只有調(diào)用done方法才能等待調(diào)用結(jié)束以后測試
            //mocha默認的等待時間是2秒,上述操作超過兩秒,報錯
            //運行命令mocha demo-5.js -t 5000重置等待時間解決
        })
    })

運行結(jié)果:跳過了添加skip方法的測試腳本

image

八、ES6測試

1、ES5寫法

src/add.js

function add(x, y) {
    return x + y;
}

module.exports = add;

test/demo-2.test.js

const chai = require("chai");
const expect = chai.expect;
var Add = require("../src/add.js");

describe('加法函數(shù)的測試', function () {
    it('1 加 1 應該等于 2', function () {
        expect(Add(1, 1)).to.be.equal(2);
    });
});

運行命令

mocha

運行結(jié)果

image

2、ES6寫法

test/demo-2.test.js

const chai = require("chai");
const expect = chai.expect;
var Add = require("../src/add.js");

describe('加法函數(shù)的測試', function () {
    it('1 加 1 應該等于 2', function () {
        expect(Add(1, 1)).to.be.equal(2);
    });
});

如果測試腳本是用ES6寫的,那么運行測試之前,需要先用Babel轉(zhuǎn)碼。

(1)安裝Babel

npm install babel-core babel-preset-es2015 --save-dev

(2)在項目目錄下面,新建一個.babelrc文件:

{
  "presets": [ "es2015" ]
}

運行命令

./node_modules/mocha/bin/mocha --require babel-core/register

運行結(jié)果

image

九、測試報告

運行mocha --reporters可以顯示所有內(nèi)置的報告格式。

image

1、spec格式

--reporter參數(shù)用來指定測試報告的格式,默認是spec格式。

mocha
等同于
mocha --reporter spec

運行結(jié)果:

image

2、tap格式

mocha --reporter tap

運行結(jié)果:

image

3、HTML格式

使用mochawesome模塊,可以生成漂亮的HTML格式的報告。

(1)安裝mochawesome模塊

npm install --save-dev mochawesome

(2)執(zhí)行測試命令

./node_modules/.bin/mocha --reporter mochawesome

上面代碼中,mocha命令使用了項目內(nèi)安裝的版本,而不是全局安裝的版本,因為mochawesome模塊是安裝在項目內(nèi)的。

(3)運行結(jié)果:

image

(4)測試結(jié)果報告在mochaawesome-reports子目錄生成。

image

(5)在瀏覽器中瀏覽html格式的測試報告

image

十、生成測試文件

Mocha支持從測試用例生成規(guī)格文件。

1、Markdown格式

mocha demo-1.test.js --recursive -R markdown > spec.md

上面命令根據(jù)test目錄的demo-1.test.js測試腳本,生成一個規(guī)格文件spec.md。-R markdown參數(shù)指定規(guī)格報告是markdown格式。

image

2、HTML格式

mocha demo-1.test.js --recursive -R doc > spec.html

上面命令根據(jù)test目錄的demo-1.test.js測試腳本,生成一個規(guī)格文件spec.html.

image

十一、在瀏覽器中測試

除了在命令行運行,Mocha還可以在瀏覽器運行。

1、首先,使用mocha init命令在指定目錄生成初始化文件。

mocha init vue-test

運行上面命令,就會在vue-test目錄下生成index.html文件,以及配套的腳本和樣式表。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Mocha</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="mocha.css">
  </head>
  <body>
    <div id="mocha"></div>
    <script src="mocha.js"></script>
    <script>mocha.setup('bdd');</script>
    <script src="tests.js"></script>
    <script>
      mocha.run();
    </script>
  </body>
</html>

2、新建一個源碼文件add.js

function add(x, y) {
    return x + y;
}

module.exports = add;

3、新建一個測試腳本tests.js

var expect = chai.expect;

describe('加法函數(shù)的測試', function () {
    it('1 加 1 應該等于 2', function () {
        expect(add(1, 1)).to.be.equal(2);
    });

    it('任何數(shù)加0等于自身', function () {
        expect(add(1, 0)).to.be.equal(1);
        expect(add(0, 0)).to.be.equal(0);
    });
});

4、然后,把這個文件,以及斷言庫chai.js,加入index.html。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Mocha</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="mocha.css">
  </head>
  <body>
    <div id="mocha"></div>
    <script src="mocha.js"></script>
    <script>mocha.setup('bdd');</script>
    <script src="add.js"></script>
    <script src="http://chaijs.com/chai.js"></script>
    <script src="tests.js"></script>
    <script>
      mocha.run();
    </script>
  </body>
</html>

5、現(xiàn)在,在瀏覽器里面打開index.html,就可以看到測試腳本的運行結(jié)果。

image

參考文檔

mocha官網(wǎng)

https://mochajs.org/

測試框架 Mocha 實例教程 by 阮一峰

https://juejin.im/entry/5941ea698d6d810058bff709

【前端單元測試入門01】Mocha與chai

http://www.itdecent.cn/p/aa53ac34e4c0

vue項目中添加單元測試

https://blog.csdn.net/weixin_33739523/article/details/92436029

vue官網(wǎng)-單元測試模塊

https://cn.vuejs.org/v2/guide/unit-testing.html#ad

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容