可以進行單元測試么_前端與單元測試

d5e76515d19c93d1aeea44be6be88551.png

先來幾個專業詞匯,這樣顯得高大上一點(不存在的=。=)

BDD: Behavior-Driven Development (行為驅動開發)TDD: Test-Driven Development (測試驅動開發)ATDD: Acceptance Test Driven Development(驗收測試驅動開發)

好,說完了,然后我們廢話不多說,直接進入正題。我會從多個測試框架入手,結合各種斷言庫,用代碼方式說明。


單元測試(Unit Testing),是指對軟件中的最小可測試單元進行檢查和驗證。

當今所有著名的框架都要進行單元測試,經過測試的框架,它的信任度顯然高于未測試的框架。

這里,我們介紹一下karma這個前端的單元測試框架。

4c567b916e296056d25d4ea8e73d387b.png
Spectacular Test Runner for Javascript?karma-runner.github.io

首先我們來安裝一波:
新建一個文件夾,然后在空文件夾中打開終端輸入

npm init -y
(sudo) npm install karma-cli -g
npm install karma karma-jasmine karma-chrome-launcher jasmine-core --save-dev
npm install karma-phantomjs-launcher --save-dev

b809e3745b98b47697e4e670227fe9fe.png

你安裝karma-cli這個倒是說得過去,可是這個jasmine是啥,這個chrome-launcherphantomjs-launcher又是啥?

沒錯,單說測試框架是不完整的,必須要有斷言庫與之相配合,這里的jasmine就是斷言庫。

48a8a443374daaab5d736b0a815e787c.png

啥是斷言(assert)

根據概念:

斷言是編程術語,表示為一些布爾表達式,程序員相信在程序中的某個特定點該表達式值為真,可以在任何時候啟用和禁用斷言驗證,因此可以在測試時啟用斷言而在部署時禁用斷言。

一言以蔽之,老子/老娘說啥就是啥!聽起來好像挺霸道的。那么具體呢?

順著karma的正常流程向下走,我們來寫一個簡單的單元測試。在終端輸入:

karma init

你會發現,需要做一個調查問卷了,問題如下:

> 請問你要用哪種測試框架呢?
> 按tab鍵選擇,按回車鍵進入下一個問題。
> jasmine 
(因為我們安裝的是jasmine,選什么斷言庫都別忘了安裝一下)> 您想要使用Require.js么?  
> 選擇yes的話,會安裝Require.js插件。
> 按tab鍵選擇,按回車鍵進入下一個問題。  
> no 
(這里我們選擇no)> 你想要在什么瀏覽器中測試呢?  
> 按tab鍵選擇,輸入空字符串進入下一個問題。  
> Chrome
> PhantomJS
>注:上面的選擇這兩個瀏覽器的原因是我們之前安裝了這兩個瀏覽器的啟動器(launcher)> 需要測試的源文件和測試命令文件放在哪呢?
你可以使用通配符(glob patterns)來匹配文件,比如:"js/*.js" 或 "test/**/*Spec.js"
輸入空字符串進入下一個問題。 
>
(這里先留空,可根據測試情況靈活配置)>在符合匹配的文件中有哪些文件可以排除在外呢?
你可以使用通配符來匹配文件,比如:"**/*.swp"
輸入空字符串進入下一個問題。 
> > 你想要Karma根據文件的變化立即做出響應么?
> yes

之后,你就會發現你的文件夾里多了一個文件:

e3829e78888ddc09bf25b58e2f20914b.png

打開這個文件,你會發現里面是一個配置項函數:

module.exports = function(config) {basePath: '', // 根路徑將會同files和excluede項中的相對路徑相關聯frameworks: ['jasmine'], // 所使用的測試框架files: [], // 這里是需要測試的文件列表,有多種配置方式exclude: [], // 測試過程中排除在外的文件列表reporters: ['progress'], // 測試結果的匯報方式,port: 9876, // web服務器接口colors: true, // 是否使用彩色報告logLevel: config.LOG_INFO, // 日志級別,可配置的值有: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUGautoWatch: true, // 是否自動觀測文檔改變并執行測試命令browsers: ["Chrome", "PhantomJS"], // 用哪些瀏覽器測試呢singleRun: false, // 持續集成模式,如果設置成true,Karma將自行捕獲瀏覽器,運行測試并根據結果退出,concurrency: Infinity // 并發數,同時跑多少個瀏覽器進行測試,默認無上限
}

默認會生成的配置項就是上面這些,更完整的配置請點我
這里稍微提一下browsers配置項,它可以配置高達8種瀏覽器:

a0711a9462d5e983db4fca5ef6af26f0.png

每一種都需要安裝對應的launcher。其中有兩個需要注意chromeHeadlessPhantomJS。這兩個是無頭瀏覽器。所謂無頭瀏覽器就是沒有腦袋的瀏覽器

8f843cffd46319c864c0fa9a31495b06.png
無頭瀏覽器即headless browser,是一種沒有界面的瀏覽器。既然是瀏覽器那么瀏覽器該有的東西它都應該有,只是看不到界面而已。因此這種瀏覽器沒有渲染UI的過程,用于測試時的速度很快。

這就回答了上文launcher是啥的問題。畢竟,沒有瀏覽器靠腦補可沒法測試啊(真實)

言歸正傳。我們回到karma測試本身。接下來,我們修改一下配置:

files: ["src/srcTest/**/*.js", "test/unit/**/*.js"]

注意,上述寫法只是配置寫法中的一種, 配置的文件位置也是隨您自己指定,更詳細的配置請點我

采用上文寫法的話,我們在files數組里面配置的第一項是需要測試的文件,第二項就是用什么方法去測試它的文件

因此,我們也在文件里創建對應的文件夾:

681f75e41cdf0cbffd7853eda5c100e3.png

這里有一個要注意的點。我們的需要測試的文件和測試驅動文件的名字是一一對應的,區別就在于測試驅動文件的名字后要加上.spec

那么我們就在srcTest的文件里面寫點什么吧....

newBee.js

// 減法函數
function minus(x) {return function(y) {return x - y;};
}

testKarma.js

// 加法函數
function add(x) {return function(y) {return x + y;};
}// 乘法函數
function multi(x) {return function(y) {return x * y;};
}//if函數測試
function ifTest(boolean) {if (boolean) {return "熱熱";} else {return "涼涼";}
}// 反轉字符串
function reverseStr (string) {return string.split("").reverse().join("");
}

e42d57c1abe155fd644142d1d98d87c3.png

那么接下來,就在.spec文件里寫入對應的測試斷言。我滴個龜龜,終于說到斷言了。

因為我們這里使用的是Jasmine,因此就先放一下它的官網。

b140912442d13b35bc4aa484e3bdbcde.png
Global?jasmine.github.io

我們結合實例來說文檔

newBee.spec.js

describe("newBee單元測試", function() {it("減法函數測試", function() {var minus7 = minus(7);expect(minus7(6)).toBe(0);});
});

testKarma.spec.js

describe("testKarma單元測試", function() {it("如果函數測試", function() {expect(ifTest(true)).toBe(true);expect(ifTest(false)).toBe("涼涼");});it("回文函數測試", function() {expect(reverseStr('abc')).toEqual('cba');})});

基本的格式就是這樣的,下面來解釋一下

// 分組describe(), 這個是可以嵌套的,并且每個單獨的測試都有beforeAll, afterAll, beforeEach和afterEach
describe("這里寫測試群組的名稱", function(){// 具體的測試,it(), 當其中所有的斷言都為true時,則通過;否則失效。it('這里寫具體測試的名稱', function(){var a = true;// 期望, expect()。 匹配,to*()// 每個匹配方法在期望值和實際值之間執行邏輯比較// 它負責告訴jasmine斷言的真假,從而決定測試的成功或失敗// 木有錯,老子/老娘說啥就是啥expect(a).toBe(true); // 這是肯定斷言expect(!a).not.toBe(true); // 這是否定斷言// jasmine內置的匹配方法有很多,亦可自定義匹配方法// toBe()// toEqual()// toMatch()// toBeUndefined()// toBeNull()// toBeTruthy()// toContain()// toBeLessThan()// toBeCloseTo()// toThrowError()// 等等等等})
})

那么,測試方法寫完了,我們來實際運行一下測試吧。打開終端,輸入:

karma start

就會在終端看到

a331798a52cfbc9aa325a2d1610e1556.png

可以看到,我們的測試在Chrome和PhantomJS瀏覽器中分別測試了的5個方法,都有2個沒有通過測試,沒錯,我們當初在寫測試的時候故意寫錯了(這是真的)。

那么我們把測試修改成真值。

newBee.spec.js

describe("newBee單元測試", function() {it("減法函數測試", function() {var minus7 = minus(7);expect(minus7(6)).toBe(1);});
});

testKarma.spec.js

it("如果函數測試", function() {expect(ifTest(true)).toBe("熱熱");expect(ifTest(false)).toBe("涼涼");
});

結果是:

e1f5a64abbd3193f5d22f655d4d7e014.png

全部SUCCESS, 撒花。

到這里,一個基本的測試流程就走完了。然而,這并非終點。

其實,還能更進一步的。我們打開終端:

npm install karma-coverage --save-dev

然后打開karma.conf.js, 添加一些配置項

// 這里配置哪些文件需要統計測試覆蓋率,例如,如果你的所有代碼文件都在src文件夾中,你就需要如下配置
preprocessors: {"src/srcTest/*.js": "coverage"
},
// 新增coverageReporter選項
// 配置覆蓋率報告的查看方式,type查看類型,可以取值html、text等等,dir輸出目錄
coverageReporter: {dir: "docs/unit",reporters: [{type: "html",subdir: "report-html"}]
},
reporters: ['progress', "coverage"] // 沒錯,reporters里面新增了一個coverage

然后保存,再運行一次karma start

接著會發現你的項目里多了一個文件夾

fda3d0530a10513497978f3c061695ca.png

用瀏覽器打開index.html。就會看到

5eaef53af2fe2fe2f5a8eaa0f351eda7.png

這就是你所寫的js的測試覆蓋率。

這樣看起來是不是高大上了一些呢?

這里就有一個問題了。普通的js可以測試,可是我是寫Vue的啊,Vue組件怎么測試呢?很簡單,Vue官網有非常詳細的測試教程。甚至還有專用的測試工具和測試說明

cb94a3739d107ef74b187ad70633c01c.png

彳亍口巴,你說的這些個單元測試看起來花里胡哨的,實際作用是什么呢?

單元測試的好處

  1. 單元測試不但會使你的工作完成得更輕松。而且會令你的設計會變得更好,甚至大大減少你花在調試上面的時間。
  2. 提高代碼質量
  3. 減少bug, 快速定位bug
  4. 使修改和重構可以更放心
  5. 顯得專業

單元測試的缺點

開發人員要花費時間在寫測試代碼上,然而又不會給你加工資...
小項目寫測試只能單純的增加開發時間和成本,然而又不會給你加工資...
我寫了測試除了懂測試的人能看懂,別人又不知道,然而還不會給你加工資...

336b309ab9c1f65b93eec0660303c7e4.png

別別別,別打我...你先聽我道(hu)理(jiao)講(man)完(chan)。

  1. 對于所編寫的代碼,你在調試上面畫了多少時間?
  2. 對于以前你自認為正確的代碼,而實際上這些代碼卻存在重大的bug,你花了多少時間在重新確認這些代碼上面?
  3. 對于一個別人報告的bug,你花了多少時間才找出導致這個bug的源碼位置?

對于那些沒有使用單元測試的程序員而言,上面這些問題所耗費的時間的是逐漸增加的,而且項目越深入,花費的時間越多;另一方面,適當的單元測試卻可以很大程度地減少這些時間,從而為你騰出足夠的時間來編寫所有的單元測試——甚至可能還有剩余的空閑時間。

更加真實的是,主流的框架必須要寫測試

不想當程序員的設計師不是好運維。 ----魯迅

作為一個程序員,如果你想要讓自己寫的框架放到github和npm上能夠為世界上的其他人所用。那么一個最基本的前提就是————代碼沒有BUG。可是,你的怎么向語言不通思維不同的人解釋你的JavaScript庫確實足夠健壯呢。這個時候就需要單元測試出場了。

主流前端框架雖然在所使用的測試庫(karma、jest、QUnit)和斷言庫(assert、jasmine、 chai)上略有差別,但Vue、React、Angular、Underscore甚至是jQuery都寫了單元測試。

來個石錘

e6fec5e1fcb0d96f7e0ee8695388000c.png

下面我們看一看Vue的測試是怎么寫的:

git clone https://github.com/vuejs/vue.git
npm install
npm run test unit // 這里可以看到單元測試
npm run test // 這里就看全部的測試

Vue的測試覆蓋率為

57e5636d86ffbb015c0c9af45830dc65.png

舉例:v-show的測試

// import Vue from 'vue'describe('Directive v-show', () => {it('should check show value is truthy', () => {const vm = new Vue({template: '<div><span v-show="foo">hello</span></div>',data: { foo: true }}).$mount()expect(vm.$el.firstChild.style.display).toBe('')})it('should check show value is falsy', () => {const vm = new Vue({template: '<div><span v-show="foo">hello</span></div>',data: { foo: false }}).$mount()expect(vm.$el.firstChild.style.display).toBe('none')})it('should update show value changed', done => {const vm = new Vue({template: '<div><span v-show="foo">hello</span></div>',data: { foo: true }}).$mount()expect(vm.$el.firstChild.style.display).toBe('')vm.foo = falsewaitForUpdate(() => {expect(vm.$el.firstChild.style.display).toBe('none')vm.foo = {}}).then(() => {expect(vm.$el.firstChild.style.display).toBe('')vm.foo = 0}).then(() => {expect(vm.$el.firstChild.style.display).toBe('none')vm.foo = []}).then(() => {expect(vm.$el.firstChild.style.display).toBe('')vm.foo = null}).then(() => {expect(vm.$el.firstChild.style.display).toBe('none')vm.foo = '0'}).then(() => {expect(vm.$el.firstChild.style.display).toBe('')vm.foo = undefined}).then(() => {expect(vm.$el.firstChild.style.display).toBe('none')vm.foo = 1}).then(() => {expect(vm.$el.firstChild.style.display).toBe('')}).then(done)})it('should respect display value in style attribute', done => {const vm = new Vue({template: '<div><span v-show="foo" style="display:block">hello</span></div>',data: { foo: true }}).$mount()expect(vm.$el.firstChild.style.display).toBe('block')vm.foo = falsewaitForUpdate(() => {expect(vm.$el.firstChild.style.display).toBe('none')vm.foo = true}).then(() => {expect(vm.$el.firstChild.style.display).toBe('block')}).then(done)})it('should support unbind when reused', done => {const vm = new Vue({template:'<div v-if="tester"><span v-show="false"></span></div>' +'<div v-else><span @click="tester=!tester">show</span></div>',data: { tester: true }}).$mount()expect(vm.$el.firstChild.style.display).toBe('none')vm.tester = falsewaitForUpdate(() => {expect(vm.$el.firstChild.style.display).toBe('')vm.tester = true}).then(() => {expect(vm.$el.firstChild.style.display).toBe('none')}).then(done)})
})

只要你的測試覆蓋率足夠高,你就可以在著名的GitHub裝逼網站Codecov搞一個覆蓋率標簽了。就像下面這個:

ae735767b79d0f15a5ee18c5632dbb90.png

怎么樣,這樣你所寫的框架,是不是就逼格滿滿?

02843ef8049471bce64ebb118f96c601.png

所以你還在等什么,測不了吃虧,測不了上當,趕緊在自己的代碼中加入測試吧,~~只要998~~,代碼逼格帶回家!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/257764.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/257764.shtml
英文地址,請注明出處:http://en.pswp.cn/news/257764.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UWP--頁面傳值

//匿名對象private void Button1_OnClick(object sender, RoutedEventArgs e){this.Frame.Navigate(typeof(PageNavigate2), new { id 1, name "LBI" });}//利用反射獲取protected override void OnNavigatedTo(NavigationEventArgs e){var parameter e.Parameter…

Android 4.4 KitKat, the browser and the Chrome WebView

Having V8 as the JavaScript engine for the new web view, the JavaScript performance if much better, besides general performance on CSS thanks to hardware acceleration Android 4.4 KitKat, the browser and the Chrome WebView轉載于:https://www.cnblogs.com/dais…

excel 行高 上下留白_拒絕加班,工作中最常用的57個Excel小技巧來了!

今天高頓君分享的 Excel小技巧&#xff0c;全是工作是最常用且簡單易操作的&#xff0c;共57個&#xff0c;希望對同學們有所幫助。&#xff08;適合版本 Excel2007及以上&#xff09;一、文件操作1、為excel文件添加打開密碼文件 - 信息 - 保護工作簿 - 用密碼進行加密。2、為…

經驗分享:三步走教你升級企業NAS設備

前幾年凡是對于數據存儲有需求的企業都已經購買了相關的NAS產品&#xff0c;不過電腦和網絡升級換代是比較頻繁的&#xff0c;幾年過去了中小企業對數據存儲的需求也水漲船高&#xff0c;然而面對當初的NAS存儲設備該如何處理呢&#xff1f;扔掉可惜使用又不如意的雞肋問題能夠…

C#索引器

索引器允許類或者結構的實例按照與數組相同的方式進行索引取值&#xff0c;索引器與屬性類似&#xff0c;不同的是索引器的訪問是帶參的。 索引器和數組比較&#xff1a; (1)索引器的索引值(Index)類型不受限制 (2)索引器允許重載 (3)索引器不是一個變量 索引器和屬性的不同點 …

獲取訪客進站關鍵詞_拼多多訪客突然下降是為什么?拼多多訪客突然暴漲又是怎么回事?...

在當下這個互聯網時代&#xff0c;可以說流量就代表這金錢。這一點在做電商的商家那里表現的就更為直觀了&#xff0c;如果你做了一個拼多多的店鋪&#xff0c;之前店鋪的流量一直都比較好&#xff0c;而現在拼多多店鋪的流量忽然下降了&#xff0c;那么店鋪中的銷售額就會受到…

微信開發之 二維碼生成類庫

最近weiphp 二次開真的有點累&#xff0c;漏洞百出。代碼維護代價有點高。 <?php /*** Created by PhpStorm.* User: bin* Date: 15-1-16* Time: 上午9:48*/ namespace Home\Common;// 微信處理類 set_time_limit(30); class Weixin{//構造方法static $qrcode_url "h…

通過Matlab實現離散序列卷積和

前言 年輕人&#xff0c;你對數學一無所知&#xff0c;你只是習慣了而已。—馮諾伊曼 Young man, in mathematics you dont understand things. You just get used to them.—John von Neumann。 一、卷積和是什么&#xff1f; 卷積的本質是描述一個瞬時動作&#xff08;激勵…

Ansible 五(inventory文件 主機清單)

Ansible 五&#xff08;inventory文件 主機清單&#xff09;Ansible 可同時操作屬于一個組的多臺主機,組和主機之間的關系通過 inventory 文件配置. 默認的文件路徑為 /etc/ansible/hosts除默認文件外,你還可以同時使用多個 inventory 文件(后面會講到),也可以從動態源,或云上…

python series用法_如何使用Python中的Series字典創建數據框?

數據框是一種二維數據結構&#xff0c;其中數據以表格格式存儲&#xff0c;以行和列的形式。它可以可視化為SQL數據表或excel工作表表示形式。可以使用以下構造函數創建它-pd.Dataframe(data, index, columns, dtype, copy)讓我們了解如何使用Series字典創建數據框。系列是“熊…

[轉載]android設置全屏和無標題

先介紹去掉標題欄的方法&#xff1a; 第一種&#xff1a;也一般入門的時候經常使用的一種方法 requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉標題欄注意這句一定要寫在setContentView()方法的前面&#xff0c;不然會報錯的 第二種&#xff1a;在AndroidManifest.xml文…

mac電腦下Tomcat和Apach配置流程(超詳細)

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 前言 本章介紹在mac 電腦下如何配置Tomcat、Apach等環境 一、Apache介紹及配置 1.XAMPP安裝 為了更好的進行各項軟件服務的配置&#xff0c;引入快捷腳本工具——XMAPP。…

MVC 分頁

后臺代碼: using Webdiyer.WebControls.Mvc; 1 public ActionResult Index(int id 1)2 {3 int pageIndex id;4 int count;5 int pageSize 7;6 7 List<News> newsList 8 newsSer.QueryByPage…

cvc 降噪_耳機降噪功能這么多,說說什么是ANC、ENC、CVC、DSP降噪

降噪功能對耳機的作用很重要&#xff0c;一是減少噪音&#xff0c;避免過度放大音量&#xff0c;從而減少對耳朵的損害。二是過濾噪音從而提高音質和通話質量。降噪可分為被動式降噪和主動式降噪。被動式降噪也就是物理降噪&#xff0c;被動式降噪是指利用物理特性將外部噪聲與…

RPC 和 RESTful

2019獨角獸企業重金招聘Python工程師標準>>> to do ... 轉載于:https://my.oschina.net/u/2002769/blog/1505410

[linx] ubuntu網絡重啟命令

/etc/init.d/networking restart #這種方式必須有/etc/network/interface文件 ifconfig eth0 down #直接重啟網卡 ifconfig eth0 up 轉載于:https://www.cnblogs.com/fantasy01/p/4229734.html

密碼學入門1——凱撒密碼和三重DES加解密

實驗目的 1、完成第一個入門加解密——凱撒密碼 2、完成當下較為流行的三重DES加解密技術 3、熟悉所學的實際運用方向 實驗準備 硬件&#xff1a;計算機或筆記本電腦 操作系統&#xff1a;Mac操作系統 IDE環境&#xff1a;Eclipse 程序語言&#xff1a;Java 一、實驗基本…

老李談JVM內存模型

老李談JVM內存模型 poptest是國內唯一一家培養測試開發工程師的培訓機構&#xff0c;以學員能勝任自動化測試&#xff0c;性能測試&#xff0c;測試工具開發等工作為目標。如果對課程感興趣&#xff0c;請大家咨詢qq&#xff1a;908821478&#xff0c;咨詢電話010-84505200。 J…

emqx 使用端口_數據傳輸、存儲、展現,EMQ X + TDengine 搭建 MQTT 物聯網數據可視化平臺...

物聯網數據采集涉及到大量設備接入、海量的時序數據傳輸&#xff0c;EMQ X 消息中間件與 TDengine 大數據平臺的組合技術棧完全能夠勝任場景中的海量時間序列監測數據的傳輸、存儲和計算。數據入庫后&#xff0c;往往需要其他方式如數據可視化系統將數據按照規則統計、展現出來…

站點CSS樣式不起作用,或僅僅有一部分起作用?隨手記

事件&#xff1a;網頁中使用了相同的樣式&#xff0c;下半部分正常顯示&#xff0c;上半部分樣式所有丟失不能顯示。解決&#xff1a;改動了相應的CSS樣式文件的編碼 這個是最沒有想到的解決的方法。怎樣調試&#xff1a;通過右鍵頁面查看編碼為UTF-8 或 GBK 看到樣式正常顯示&…