大前端的自動化工廠(5)—— 基於Karma+Mocha+Chai的單元測試和介面測試

大史不說話發表於2018-11-02

大前端的自動化工廠(5)—— 基於Karma+Mocha+Chai的單元測試和介面測試
大前端的自動化工廠(5)—— 基於Karma+Mocha+Chai的單元測試和介面測試

一. 前端自動化測試

大多數前端開發者對測試相關的知識是比較缺乏的,一來是開發節奏很快,來不及寫,另一方面團隊裡也配備了“人肉測試機”,完全沒必要自己來。但隨著專案體量的增大,許多人維護同一份程式碼,經常會出現有些函式莫名其妙地結果不對了,或者某個介面的入參變了,又或者哪位大哥把後端返回的資料結構給改了。每天工作的時間裡被拉來拉去幫人定位問題,結果花了很多時間卻發現大部分都是別人的鍋。每當遇到專案上線,那就更熱鬧了,跟著其他“人肉測試機”大家一起點點點……

很多團隊都有個通病,凡是出了問題,先往前端身上推,然後前端各種檢測排查,到最後是誰的鍋,誰呵呵一笑然後領走就完了,如果你也曾因此心裡印下了不計其數的草泥馬的馬蹄印,那我強烈建議你學習【前端自動化測試】相關的知識,或許你不會經常用到它,但在組內互懟和甩鍋的環節絕對能助你一臂之力。當然總有一天,你會發現測試的價值遠不止這樣。它對大型專案提供的可靠性保障是人力無法比擬的

前端很流行這樣一句話:如果你覺得單元測試沒什麼用,只能說明你做的專案不夠大。

二. 工具簡介

2.1 Karma

官方網址:https://karma-runner.github.io/2.0/index.html

Karma為前端自動化測試提供了跨瀏覽器測試的能力,可以自動在Chrome,Firefox,IE等主流瀏覽器依次跑完測試用例,同時也支援headless瀏覽器(入phantomJs)中執行測試用例。webpack+babel可以主動為想要適配的瀏覽器提供轉碼和墊片補丁引入能力,而Karma可以為最終的結果提供驗證能力。Karma的配置方式可以閱讀《webpack4.0各個擊破(9)——Karma篇》進行了解。

2.2 Mocha

Mocha是前端自動化測試框架,測試框架需要解決相容不同風格斷言庫測試用例分組同步非同步測試架構生命週期鉤子等框架級的能力。

  • Mocha的基本語法
describe(`我現在要測某一個頁面的幾個功能`,function(){
    describe(`現在要測XX功能`,function(){
        it(`某個變數的值應該是數字`,function(){
            //寫斷言
        })
    });
     describe(`現在要測YY功能`,function(){
        it(`某個陣列長度應該不小於10`,function(){
            //寫斷言
        })
    });
})
  • 非同步測試語法
describe(`現在要測XX功能`,function(){
    it(`某個變數的值應該是數字`,function(done){
        //寫斷言
        //手動呼叫done()表示非同步結束,類似於Promise中的resolve
    })
});
  • 不同風格的斷言庫

    支援should.js,expect.js及node核心斷言模組assert等。

  • 生命週期鉤子

    生命週期鉤子一般用來建立和清理環境或全域性變數。


describe(`hooks`, function() {
  before(function() {
    // runs before all tests in this block
  });
  after(function() {
    // runs after all tests in this block
  });
  beforeEach(function() {
    // runs before each test in this block
  });
  afterEach(function() {
    // runs after each test in this block
  });
  // test cases
});

2.3 Chai

Chai是一個斷言庫合集,支援expect,assert,should斷言語法,非專業測試崗位其實沒必要深究,瞭解使用方法就可以了。使用示例:

expect(bar).to.not.exist;//斷言變數bar不存在
expect(data).to.have.ownProperty(`length`);//斷言data有length屬性
expect(name).to.be.a(`string`);//斷言name是一個字串
assert.equal(value1,value2);//斷言value1和value2相等
Tim.should.be.an.instanceof(Person);//斷言Tim是Person類的例項

上面的語法在引入了Chai後都是支援的,當斷言不成立時,結果報告中會給出明確標記。

三. 基於Chai的自動化單元測試

單元測試的原理並不算複雜,相當於另外編寫了一套程式,把業務邏輯中的指令碼檔案當做模組引入,模擬其執行環境(例如需要的瀏覽器型別,全域性變數等),然後使用一組或若干組覆蓋不同使用場景的引數來呼叫想要測試的函式單元,並判斷函式返回的結果是否和預期的相同。

簡單地說,自動化測試工具只是取代了一個照著Excel表格測試並記錄結果的人力資源。

測試用例檔案的基本寫法:

var chai = require(`chai`);//引入斷言庫
var expect = chai.expect;//使用expect語法
//引用原始碼中的業務邏輯模組;
var ColorFac = require(`../../../../src/components/Example/colorFac`);

describe("ColorFac Module Test", function () {
  it("should return a luminanced color", function () {
      //呼叫原始碼中業務邏輯模組中的方法;
    var color = ColorFac.luminate("#fff", "-0.5");
      //編寫測試斷言
    expect(color).is.not.empty;
  });
});

單元測試報告:

大前端的自動化工廠(5)—— 基於Karma+Mocha+Chai的單元測試和介面測試

使用Webpack + Karma + Mocha + Chai進行自動化測試(單元測試+程式碼覆蓋率)的方法可以檢視《webpack4.0各個擊破(9)——Karma篇》

四. 基於Chai-http的自動化介面測試

Chai-Http是基於Chai擴充套件的外掛,可用於測試與http請求相關的邏輯程式碼。開發中也可以利用PostMan或是DocLever來管理介面並進行介面測試。介面測試的執行方式和單元測試很類似,區別在於測試用例的寫法。假設介面測試的用例都寫在/test/apis/apis.js中,配置方式如下:

Karma.api.conf.js:

var path = require(`path`);
module.exports = function(config) {
    config.set({
        files: [
            `test/apis/apis.js`
        ],
        // frameworks to use
        frameworks: [`mocha`],
        preprocessors: {
            // only specify one entry point
            // and require all tests in there
            `test/apis/apis.js`: [`webpack`]
        },
        reporters: [`mocha`],
        webpack: {
            mode: `none`,
        },
        webpackMiddleware: {
            noInfo: true
        },
        plugins: [
            require("karma-webpack"),
            require("karma-mocha"),
            require("karma-chai"),
            require("karma-chrome-launcher"),
            require("karma-mocha-reporter"),
        ],
        browsers: [`Chrome`]
    });
};

/test/apis/apis.js:(測試用例的語義化非常明顯,程式碼基本不需要解釋)。

var chai = require(`chai`);
var chaiHttp = require(`chai-http`);
var expect = chai.expect;
chai.use(chaiHttp);

//define address
const ADDRESS = "http://localhost:3001";
//open a http connection
var requester = chai.request(ADDRESS);
describe(`列表服務APIS測試`,function () {

    it(`GET /healthmap/chart1 應該返回包含legendData欄位的資料`,function (done) {
        chai.request(ADDRESS).get(`/healthmap/chart1`)
        .end((err,res)=>{
            var data = JSON.parse(res.text);
            expect(res).to.have.status(200);
            expect(data.data).to.have.ownProperty(`legendData`);
            done();
        })
    });
    
    it(`GET /operationdashboard/systemwarn 應該返回字串`,function (done) {
        chai.request(ADDRESS).get(`/operationboard/systemwarn`)
        .end((err,res)=>{
            var data = JSON.parse(res.text);
            expect(res).to.have.status(200);
            expect(data.data).to.be.a(`String`);
            done();
        })
    });
})

命令列裡啟動Karma跑一下介面測試,就可以看到結果:

大前端的自動化工廠(5)—— 基於Karma+Mocha+Chai的單元測試和介面測試

測試用例沒通過的介面全都被標記出來了,省心省力。

相關文章