自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

測試你的前端代碼 - part2(單元測試)

開發(fā) 開發(fā)工具
本文將會介紹前端單元測試的內(nèi)容。

測試你的前端代碼 - part2(單元測試)

上一篇文章《測試你的前端代碼 - part1(介紹)》中,我介紹了關(guān)于前端測試的基本知識,從本文開始將具體介紹測試技術(shù)。

一、單元測試

上一節(jié)有討論過,單元測試就是以代碼單元為單位進(jìn)行測試,代碼單元可以是一個函數(shù),一個模塊,或者一個類。很多人認(rèn)為大多數(shù)測試都應(yīng)該叫單元測試,其實我的觀點還是那句話,無所謂怎么叫,名字叫什么都行。只要你做了足夠多的測試,能夠保證你部署到線上的生產(chǎn)代碼沒有問題就可以了。

單元測試是最容易理解、也最容易實現(xiàn)的測試方式。給單元測試一個輸入,讓它自動執(zhí)行,將輸出結(jié)果和預(yù)期結(jié)果做對比看其是否正確(輸入可以是一個函數(shù)參數(shù),輸出就是函數(shù)的返回值)。

在寫單元測試的時候,盡量將你的單元測試獨立出來,不要幾個單元互相引用。養(yǎng)成這樣良好的測試習(xí)慣。

二、測試 Calculator 應(yīng)用

***節(jié)中提到過,為了這系列博文,我寫了一個計算器應(yīng)用,后面都會拿它進(jìn)行測試。理論就講到這里,一起來看一下 Calculator 應(yīng)用吧,源代碼在這里。主要有兩個組件: keypad 和 display ,它們自身都是 React 單元,也都沒有引用其他單元,后面會介紹如何對它們進(jìn)行測試。

(如果你已經(jīng)看了代碼可能已經(jīng)發(fā)現(xiàn)了我沒有使用 JSX。因為我不想進(jìn)行轉(zhuǎn)譯?,F(xiàn)在 Node 和所有流行的瀏覽器都已經(jīng)完全支持 ES6 了,那么作為一個例子來講,讓它直接運行會更好一些。雖然它不能運行在 IE 上,不過也沒關(guān)系,如果是一個真實的線上項目,我會進(jìn)行轉(zhuǎn)譯的。)

還有一個問題是按鍵和展示的邏輯問題,必須要有代碼來控制當(dāng)點擊按鍵的時候發(fā)生什么。這里的按鍵包括數(shù)字鍵(如“1”,“5”)和操作鍵(如“+”,“=”)。按通常的做法,我把組件設(shè)計成了展示型組件(鍵盤)和容器型組件。容器型組件在我的 App 中是唯一包含 state 的組件,它要考慮當(dāng)發(fā)生按鍵行為的時候 App 內(nèi)在邏輯的問題。

三、“calculator”模塊

處理邏輯問題的代碼是一個單獨的模塊——calculator。這個模塊對于單元測試是很***的例子。因為它沒有對 I/O 和 UI 的依賴。你也應(yīng)該盡量使你的應(yīng)用邏輯上保持獨立——模塊不依賴于 I/O 和 UI。

對于 Web 應(yīng)用來講,I/O 是什么?沒有文件和數(shù)據(jù)庫的操作?其實不僅僅是這樣,還有 Ajax 調(diào)用,本地存儲,DOM 操作等,對我而言,任何和瀏覽器 API 有關(guān)的都是 I/O 操作。

我是怎么把計算邏輯從 React 組件中分離出來的呢?其實很簡單,其內(nèi)在邏輯是計算,我把他封裝到一個模塊中就可以了。

這個模塊的實現(xiàn)也很容易——它接收一個計算器 state(一個對象)和一個字符(數(shù)字或者操作符),返回一個新的計算器 state。如果你用過 Redux,它很像 Redux 的 reducer 模式(如果你沒用過 Redux 也沒關(guān)系)。但是如果一直由上一個 state 獲取下一個 state,怎么能回到初始狀態(tài)呢?這里還有一個模塊叫做 initialState,通過它可以初始化計算器。計算器的 state 并不是完全黑盒的,它包含了一個字段叫做 display,可以把你想要展示的 state 顯示在計算器應(yīng)用上。

如果你沒有耐心看源代碼的話,我們一起來看下這里面最重要的部分,應(yīng)用中算法的細(xì)節(jié)其實不重要。

  1. module.exports.initialState = { display: '0', initial: true } 
  2.  
  3. module.exports.nextState = (calculatorState, character) => { 
  4.   if (isDigit(character)) { 
  5.     return addDigit(calculatorState, character) 
  6.   } else if (isOperator(character)) { 
  7.     return addOperator(calculatorState, character) 
  8.   } else if (isEqualSign(character)) { 
  9.     return compute(calculatorState) 
  10.   } else { 
  11.     return calculatorState 
  12.   } 
  13.  
  14. //.... 

再次強調(diào)這里的實現(xiàn)細(xì)節(jié)并不重要,重要的是模塊的設(shè)計,它暴露出來的函數(shù)非常簡單——給一個 state,得到下一個 state。

這就是我們在 test-calculator 中所做的事情。那么接下來怎么進(jìn)行測試呢?使用測試框架,目前比較流行的框架是 Mocha ,我們就用它。不過像 Jest,Jasmine,Tape等框架也都行,隨意使用你喜歡的測試框架。

四、用 Mocha 進(jìn)行單元測試

所有的測試框架都類似,寫測試代碼調(diào)用被測函數(shù),通過測試框架運行他們,其中運行它們的代碼通常叫做“runner”。

Mocha runner 叫做 “mocha”,如果你看測試腳本的 package.json,可以看到:

  1. "scripts": { 
  2.  ... 
  3.      "test": "mocha 'test/**/test-*.js' && eslint test lib", 
  4.  ... 
  5.  }, 

它會運行 test 文件夾中所有以 test- 開頭的文件,你可以復(fù)制我的 repo,npm install 后,運行 npm test 自己試試。

(順便提一句,把所有測試都放在測試目錄,并且測試目錄放在 package 的根目錄是一個公認(rèn)的 npm package 約定,如果你不想讓人覺得你不專業(yè)的話,***還是遵守這一約定。)

運行它,會得到如下輸出:

用 Mocha 進(jìn)行單元測試

這里有 14 個測試通過的提示信息,如果沒通過,就會有紅色提示出現(xiàn)。

我們看下面代碼:

  1. const {describe, it} = require('mocha') 
  2.    const {expect} = require('chai') 
  3.    const calculator = require('../../lib/calculator') 
  4.  
  5.    describe('calculator', function () { 
  6.      const stream = (characters, calculatorcalculatorState = calculator.initialState) => 
  7.        !characters 
  8.          ? calculatorState 
  9.          : stream(characters.slice(1), 
  10.                   calculator.nextState(calculatorState, characters[0])) 
  11.  
  12.      it('should show initial display correctly', () => { 
  13.        expect(calculator.initialState.display).to.equal('0') 
  14.      }) 
  15.      it('should replace 0 in initialState', () => { 
  16.        expect(stream('4').display).to.equal('4') 
  17.      }) 
  18.    //... 

首先引入 mocha 和斷言常量 expect,這里只引入我們需要的函數(shù):describe,it 和 expect。接下來引入我們要測試的模塊 calculator。

準(zhǔn)備開始測試,用 it 函數(shù)來表達(dá):

  1. it('should show initial display correctly', () => { 
  2.       expect(calculator.initialState.display).to.equal('0') 
  3.   }) 

it 函數(shù)接收一個字符串(用來表示測試結(jié)果)和一個函數(shù)(待測函數(shù))。it 測試不能單獨運行,它們必須組成一個測試組。所以如代碼中所示,用 describe 函數(shù)定義測試組,里面包含了若干個 it 函數(shù)。

測試函數(shù)中寫什么呢?可以寫任何想寫的東西,在這個例子中我們測試了初始狀態(tài)所顯示的是不是 0。如果我們自己來實現(xiàn)怎么實現(xiàn)呢,比如可以像如下代碼:

  1. if (calculator.initialState.display !== '0') 
  2.     throw 'failed' 

對于這個問題,上面代碼也是可以測出來的。但是 expect 包含了很多特性可以使測試變得更簡單,比如可以測試數(shù)組或者對象是否和一個給定的值相等。這就是單元測試的要點,即運行一個函數(shù),或一組函數(shù),檢查其 運行結(jié)果 是否和 預(yù)期結(jié)果 一致。

五、編寫單元可測的代碼

上面的很簡單對吧!其實對于單元測試來講,難的并不是單元測試本身,而是分離代碼的藝術(shù),把代碼盡量分離成單元可測的模塊。單元可測的代碼一般都是不依賴于其他模塊、不依賴于 I/O 的代碼。這是比較困難的,大多數(shù)人都傾向于把邏輯代碼、I/O 代碼和 UI 代碼寫到一起。困難是困難,但不是說做不到,有很多技巧可以使用,比如你的代碼中有一些驗證字段,那么你就可以把驗證代碼組織到一起形成函數(shù),再對這個驗證函數(shù)進(jìn)行測試。

六、測試代碼是運行在 NodeJS 下的!?

注意一個重要的事情——單元測試是在 NodeJS 下運行的!而計算器應(yīng)用是運行在瀏覽器端的,上面的生產(chǎn)代碼都是在 NodeJS 下進(jìn)行測試的,這也可以嗎?

當(dāng)然可以。因為我們的代碼是同構(gòu)的,它可以運行在瀏覽器端和 NodeJS 上。如果你的代碼沒有使用任何 I/O,就是說沒有對瀏覽器做任何的特化處理,那么它就沒有理由不能運行在 NodeJS 上。另外,如果你使用了require,它既可以被本地的 NodeJS 識別,也可以被像 Webpack 一樣的打包器識別。你看代碼中的package.json,就可以看到我們就是使用了 Webpack,用 require 進(jìn)行代碼打包:

  1. "scripts": { 
  2.     "build": "webpack && cp public/* dist", 
  3.     ... 
  4.  } 

代碼中使用 require 來引入 React 或者其他模塊,這不論是在 NodeJS 中還是瀏覽器中都是通用的。

七、在瀏覽器中運行單元測試

我們還可以使用另一個測試框架,Karma 。使用它可以在瀏覽器中運行 Mocha 代碼,但是這里表達(dá)一下我的淺見:單元測試能在 Node 下運行就在 Node 下運行,因為很容易執(zhí)行和 debug(當(dāng)然現(xiàn)在在瀏覽器中執(zhí)行也很方便)。并且如果代碼不需要轉(zhuǎn)譯的話,執(zhí)行的也非常快。

但是我們的代碼沒有在瀏覽器中測試確實是個問題,因為我們并不真正地知道代碼在瀏覽器中運行會是什么樣子。瀏覽器中的 JS 執(zhí)行環(huán)境和 NodeJS 環(huán)境可能會有微妙的差別。

八、總結(jié)

本文中主要介紹了什么:

  • 介紹了如何使用 Mocha (和 Chai)創(chuàng)建單元測試;
  • 介紹了單元測試就是以代碼單元為單位進(jìn)行測試,這個代碼單元是獨立于其他模塊的。
  • 介紹了設(shè)計模塊時應(yīng)該獨立于其他模塊。如果一定要有依賴,那么可以 mock 一個其他模塊對本模塊進(jìn)行單元測試,或者進(jìn)行集成測試。
  • 介紹了我們測試的代碼單元應(yīng)該是同構(gòu)的,這樣就可以在 NodeJS 環(huán)境下進(jìn)行測試了。
  • 介紹了如何寫同構(gòu)代碼——沒有 I/O操作、使用 require 引入模塊、使用 Webpack 來打包模塊以使其符合瀏覽器運行環(huán)境。

下篇文章我們介紹端到端測試,把我們的代碼在真實環(huán)境(瀏覽器)中測試。請看下一篇文章《測試你的前端代碼 - part3(端到端測試)》。

點擊《測試你的前端代碼 - part2(單元測試)》閱讀原文。

【本文是51CTO專欄作者“胡子大哈”的原創(chuàng)文章,轉(zhuǎn)載請聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2017-03-30 08:23:50

測試前端代碼

2016-09-21 15:35:45

Javascript單元測試

2017-01-14 23:42:49

單元測試框架軟件測試

2022-08-02 08:07:24

單元測試代碼重構(gòu)

2021-10-12 19:16:26

Jest單元測試

2022-03-15 11:55:24

前端單元測試

2011-05-16 16:52:09

單元測試徹底測試

2020-08-18 08:10:02

單元測試Java

2016-09-14 21:55:33

前端測試Karma

2023-07-26 08:58:45

Golang單元測試

2011-08-11 13:02:43

Struts2Junit

2017-01-16 12:12:29

單元測試JUnit

2017-01-14 23:26:17

單元測試JUnit測試

2011-06-14 15:56:42

單元測試

2022-05-12 09:37:03

測試JUnit開發(fā)

2017-03-23 16:02:10

Mock技術(shù)單元測試

2021-05-05 11:38:40

TestNGPowerMock單元測試

2017-09-13 15:05:10

React前端單元測試

2016-09-26 16:42:19

JavaScript前端單元測試

2017-09-10 17:41:39

React全家桶單元測試前端測試
點贊
收藏

51CTO技術(shù)棧公眾號