什么是單元測試
單元測試(unit testing)是指對軟件中的最小可測試單元進(jìn)行檢查和驗(yàn)證。
簡單來說,單元
就是人為規(guī)定的最小的被測功能模塊。單元測試是在軟件開發(fā)過程中要進(jìn)行的最低級別的測試活動,軟件的獨(dú)立單元將在與程序的其他部分相隔離的情況下進(jìn)行測試。
測試框架
測試框架的作用是提供一些方便的語法來描述測試用例,以及對用例進(jìn)行分組。
斷言(assertions)
斷言是單元測試框架中核心的部分,斷言失敗會導(dǎo)致測試不通過,或報告錯誤信息。
對于常見的斷言,舉一些例子如下:
- 同等性斷言 Equality Asserts
expect(sth).toEqual(value)
expect(sth).not.toEqual(value)
- 比較性斷言 Comparison Asserts
expect(sth).toBeGreaterThan(number)
expect(sth).toBeLessThanOrEqual(number)
- 類型性斷言 Type Asserts
expect(sth).toBeInstanceOf(Class)
- 條件性測試 Condition Test
expect(sth).toBeTruthy()
expect(sth).toBeFalsy()
expect(sth).toBeDefined()
斷言庫
斷言庫主要提供上述斷言的語義化方法,用于對參與測試的值做各種各樣的判斷。這些語義化方法會返回測試的結(jié)果,要么成功、要么失敗。常見的斷言庫有 Should.js, Chai.js 等。
測試用例 test case
為某個特殊目標(biāo)而編制的一組測試輸入、執(zhí)行條件以及預(yù)期結(jié)果,以便測試某個程序路徑或核實(shí)是否滿足某個特定需求。
一般的形式為:
it('should ...', function() {
...
expect(sth).toEqual(sth);
});
測試套件 test suite
通常把一組相關(guān)的測試稱為一個測試套件
一般的形式為:
describe('test ...', function() {
it('should ...', function() { ... });
it('should ...', function() { ... });
...
});
spy
正如
spy
字面的意思一樣,我們用這種“間諜”來“監(jiān)視”函數(shù)的調(diào)用情況
通過對監(jiān)視的函數(shù)進(jìn)行包裝,可以通過它清楚的知道該函數(shù)被調(diào)用過幾次、傳入什么參數(shù)、返回什么結(jié)果,甚至是拋出的異常情況。
var spy = sinon.spy(MyComp.prototype, 'componentDidMount');
...
expect(spy.callCount).toEqual(1);
stub
有時候會使用
stub
來嵌入或者直接替換掉一些代碼,來達(dá)到隔離的目的
一個stub
可以使用最少的依賴方法來模擬該單元測試。比如一個方法可能依賴另一個方法的執(zhí)行,而后者對我們來說是透明的。好的做法是使用stub 對它進(jìn)行隔離替換。這樣就實(shí)現(xiàn)了更準(zhǔn)確的單元測試。
var myObj = {
prop: function() {
return 'foo';
}
};
sinon.stub(myObj, 'prop').callsFake(function() {
return 'bar';
});
myObj.prop(); // 'bar'
mock
mock
一般指在測試過程中,對于某些不容易構(gòu)造或者不容易獲取的對象,用一個虛擬的對象來創(chuàng)建以便測試的測試方法
廣義的講,以上的 spy 和 stub 等,以及一些對模塊的模擬,對 ajax 返回值的模擬、對 timer 的模擬,都叫做 mock 。
測試覆蓋率(code coverage)
用于統(tǒng)計測試用例對代碼的測試情況,生成相應(yīng)的報表,比如 istanbul
是常見的測試覆蓋率統(tǒng)計工具
TDD
全稱:Test Driven Development(測試驅(qū)動開發(fā))。
測試驅(qū)動開發(fā)是敏捷開發(fā)中的一項(xiàng)核心實(shí)踐和技術(shù),也是一種設(shè)計方法論。TDD的原理是在開發(fā)功能代碼之前,先編寫單元測試用例代碼,測試代碼確定需要編寫什么產(chǎn)品代碼。TDD的基本思路就是通過測試來推動整個開發(fā)的進(jìn)行,但測試驅(qū)動開發(fā)并不只是單純的測試工作,而是把需求分析,設(shè)計,質(zhì)量控制量化的過程。TDD首先考慮使用需求(對象、功能、過程、接口等),主要是編寫測試用例框架對功能的過程和接口進(jìn)行設(shè)計,而測試框架可以持續(xù)進(jìn)行驗(yàn)證。
TDD風(fēng)格的測試提供了suite()
, test()
, suiteSetup()
,suiteTeardown()
, setup()
, 和teardown()
這幾個函數(shù)
BDD
全稱:Behaviour Driven Development(行為驅(qū)動開發(fā))。
BDD中有兩個大的概念:測試先行和系統(tǒng)設(shè)計。
行為驅(qū)動開發(fā)是一種敏捷軟件開發(fā)的技術(shù),它鼓勵軟件項(xiàng)目中的開發(fā)者、QA和非技術(shù)人員或商業(yè)參與者之間的協(xié)作。主要是從用戶的需求出發(fā),強(qiáng)調(diào)系統(tǒng)行為。BDD最初是由Dan North在2003年命名,它包括驗(yàn)收測試和客戶測試驅(qū)動等的極限編程的實(shí)踐,作為對測試驅(qū)動開發(fā)的回應(yīng)。
總之:在項(xiàng)目之初,由客戶、開發(fā)人員、測試人員一起通過充分的溝通對系統(tǒng)的行為進(jìn)行設(shè)計,由測試人員以接近自然語言的方式編寫可以描述系統(tǒng)行為的測試用例,然后由開發(fā)人員編寫相關(guān)的實(shí)現(xiàn)代碼,并確保該測試用例通過。循環(huán)這個過程實(shí)現(xiàn)整個系統(tǒng)的功能。
BDD測試提供了describe()
,context()
,it()
,specify()
,before()
,after()
,beforeEach()
和afterEach()
這幾種函數(shù)。
context()
是describe()
的別名,二者的用法是一樣的。最大的作用就是讓測試的可讀性更好,組織的更好。相似地,specify()是it()的別名。
Mocha
Mocha是在node.js和瀏覽器上運(yùn)行的功能豐富的JavaScript測試框架,使異步測試變得簡單而有趣。摩卡測試串行運(yùn)行,允許靈活準(zhǔn)確的報告,同時將未捕獲的異常映射到正確的測試用例。
mocha默認(rèn)會執(zhí)行
test
目錄下的所有測試,不要去改變默認(rèn)目錄。2012發(fā)布重大版本
Jasmine
Jasmine是JavaScript的行為驅(qū)動開發(fā)測試框架。它不依賴于瀏覽器,DOM或任何JavaScript框架。因此它適用于網(wǎng)站,Node.js項(xiàng)目或JavaScript可運(yùn)行的任何地方。
Enzyme
Enzyme是React的JavaScript測試工具,可以更容易地斷言,操縱和遍歷React Components的輸出。
Enzyme的API和jQuery操作DOM一樣靈活易用。(因?yàn)槠涫褂玫氖?a target="_blank" rel="nofollow">cheerio庫來解析虛擬DOM,而cheerio的目標(biāo)則是做服務(wù)器端的jQuery)
Enzyme兼容大多數(shù)斷言庫和測試框架,如
chai
、mocha
、jasmine
等。
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import MyComponent from './MyComponent';
import Foo from './Foo';
describe('<MyComponent />', () => {
it('renders three <Foo /> components', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find(Foo)).to.have.length(3);
});
it('renders an `.icon-star`', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.icon-star')).to.have.length(1);
});
it('renders children when passed in', () => {
const wrapper = shallow((
<MyComponent>
<div className="unique" />
</MyComponent>
));
expect(wrapper.contains(<div className="unique" />)).to.equal(true);
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = shallow(<Foo onButtonClick={onButtonClick} />);
wrapper.find('button').simulate('click');
expect(onButtonClick).to.have.property('callCount', 1);
});
});
Jest
Jest 是 FaceBook 用來測試 JavaScript 應(yīng)用的一套測試框架,這些應(yīng)用當(dāng)然也包括了 React 應(yīng)用。它的優(yōu)點(diǎn)之一是自帶了對 React 的支持,同時也很容易支持其它框架。
對比
優(yōu)缺點(diǎn)
優(yōu)點(diǎn) | 缺點(diǎn) | |
---|---|---|
Mocha | 開源<br />用于瀏覽器和服務(wù)器測試<br />可以自定義斷言庫<br />易于安裝<br />允許任何能夠拋出失敗異常測試庫的使用<br />部分CI服務(wù)器和其它插件的支持 <br />功能上更多是面向BDD或者行為面向TDD<br />高擴(kuò)展性<br />輕而易舉的進(jìn)行異步測試 | 不能用于React Native測試 |
Jasmine | 開源<br />簡單<br />BDD測試框架<br />也可以用于tdd<br />易于安裝 | 不能用于React Native測試 |
Enzyme | 開源<br />Enzyme庫可以更容易地斷言,操縱和遍歷React Components的輸出 | 只能結(jié)合其他測試框架用 |
Jest | 開源 <br />可以測試React Native應(yīng)用程序<br />并行測試運(yùn)行<br />快速<br />開箱即用的代碼覆蓋率<br />測試用例并行執(zhí)行,更高效<br />強(qiáng)大的 Mock 功能<br />集成 JSDOM,可以直接進(jìn)行 DOM 相關(guān)的測試<br />更易用簡單,幾乎不需要額外配置<br />有快照測試功能,可對 React 等框架進(jìn)行 UI 測試 | React組件測試不細(xì)膩<br />集成度高,不太靈活 |
社區(qū)影響
搜索熱度
那些公司在用
更多對比可以移步:Mocha vs. Jasmine vs. Jest
React Native單元測試現(xiàn)有方案
目前能夠測試React Native組件的只有Jest框架,所以市場上的現(xiàn)有方案都是Jest或者和其他測試框架組合框架,如下:
- Jest
- Jest + Mocha
- Jest + Jasmine
- Jest + Enzyme
- Jest+Enzyme+storybook
優(yōu)點(diǎn) | 缺點(diǎn) | |
---|---|---|
Jest | 測試用例并行執(zhí)行,更高效<br />強(qiáng)大的 Mock 功能<br />內(nèi)置的代碼覆蓋率檢查,不需要在引入額外的工具<br />集成 JSDOM,可以直接進(jìn)行 DOM 相關(guān)的測試<br />更易用簡單,幾乎不需要額外配置<br />可以直接對 ES Module Import 的代碼測試<br />有快照測試功能,可對 React 等框架進(jìn)行 UI 測試 | |
Jest + Mocha | 添加了Mocha的斷言庫可自定義。 | |
Jest + Jasmine | 添加了Jasmine的spy功能,還有就是更方便的操作dom | |
Jest + Enzyme | 除了擁有Jest特點(diǎn),同時具有Enzyme庫可以更容易地斷言,操縱和遍歷React Components的輸出 |
測試原理
javascript的單元測試有:Karma + Jasmine、Mocha + should、Jest、Enzyme。
Karma 主要用于angular測試
javaScript
- Jest
- 用于React Native應(yīng)用的不同的自動化測試框架
- Mocha中文文檔
- 對 React 組件進(jìn)行單元測試 ??
- 進(jìn)入Jasmine的世界——超強(qiáng)Javascript測試框架
- jasmine官方api參考
- Mocha中文文檔
- 使用jest+enzyme進(jìn)行react項(xiàng)目測試 - 測試手法篇
- 前端測試框架Jest系列教程
- enzyme簡介——Airbnb的React測試框架
- 基于 Jest + Enzyme 的 React 單元測試
iOS
- XCTest 蘋果官方的單元測試庫
- Quick
- Nimble
- iOS 單元測試
- iOS自動化測試的那些干貨
Android
- JUnit4
- AndroidJUnitRunner Android官方單元測試庫
- EspressoUI測試