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

測(cè)試你的前端代碼 - part4(集成測(cè)試)

開(kāi)發(fā) 開(kāi)發(fā)工具
本文介紹集成測(cè)試(Integration Testing)。

測(cè)試你的前端代碼 - part4(集成測(cè)試)

上一篇文章《測(cè)試你的前端代碼 - part3(端到端測(cè)試)》中,我介紹了關(guān)于端到端測(cè)試的基本知識(shí),從本文介紹集成測(cè)試(Integration Testing)。

一、集成測(cè)試

我們已經(jīng)看過(guò)了“測(cè)試光譜”中的兩種測(cè)試:?jiǎn)卧獪y(cè)試和端到端測(cè)試。實(shí)際工作中的測(cè)試經(jīng)常是介于這兩種測(cè)試之間的,包括我在內(nèi)的大多數(shù)人通常把這種測(cè)試叫做集成測(cè)試。

二、關(guān)于術(shù)語(yǔ)

和許多 TDD 愛(ài)好者聊過(guò)以后,我了解了他們對(duì)“集成測(cè)試”這個(gè)詞有一些不同的理解。他們認(rèn)為集成測(cè)試是測(cè)試代碼邊界,即代碼對(duì)外的接口部分。

比如他們代碼中有 Ajax,localStorage 或者 IndexedDB 操作,那其代碼就不能做單元測(cè)試,這時(shí)他們會(huì)把這些代碼打包成接口,然后在做單元測(cè)試的時(shí)候 mock 這些接口。當(dāng)真正測(cè)試這些接口的時(shí)候才稱(chēng)作“集成測(cè)試”。從這個(gè)角度來(lái)說(shuō),“集成測(cè)試”就是在純的單元測(cè)試以外,測(cè)試與外部“真實(shí)世界”相關(guān)的代碼。

而我和其他一些人則傾向于認(rèn)為“集成測(cè)試”是將兩個(gè)或多個(gè)單元測(cè)試綜合起來(lái)進(jìn)行測(cè)試的一種方法。通過(guò)接口把與外部相關(guān)的代碼打包到一起,再 mock,只是其中的一種實(shí)現(xiàn)方式。

我的觀點(diǎn)里,決定是否使用真實(shí)場(chǎng)景的 Ajax 或者其他 I/O 操作進(jìn)行集成測(cè)試(即不使用 mock),取決于是否能夠保證測(cè)試速度足夠快,并且能夠穩(wěn)定測(cè)試(不發(fā)生 flaky 的情況)。如果可以確定這樣的話,那盡管用真實(shí)場(chǎng)景進(jìn)行集成測(cè)試就好了。不過(guò)如果很慢或者發(fā)生不穩(wěn)定測(cè)試的情況,那還是用 mock 會(huì)好一些。

在我們的例子中,計(jì)算器應(yīng)用唯一的真實(shí) I/O 就是操作 DOM 了,沒(méi)有 Ajax 調(diào)用,所以不存在上面的問(wèn)題。

三、mock DOM

這就引出了一個(gè)問(wèn)題:在集成測(cè)試中是否需要 mock DOM?重新思考一下上面我說(shuō)的標(biāo)準(zhǔn),使用真實(shí) DOM 是否會(huì)使測(cè)試變慢呢,答案是會(huì)的。使用真實(shí) DOM 意味著要用瀏覽器,用瀏覽器意味著測(cè)試速度變慢,測(cè)試變的不穩(wěn)定。

那么是不是要么只能盡量把操作 DOM 的代碼分離出來(lái),要么只能使用端到端測(cè)試了呢?其實(shí)這兩種方法都不好。還有另一種解決方案:jsdom。一個(gè)非常棒的包,用它自己的話說(shuō):這是在 NodeJS 中實(shí)現(xiàn)的 DOM。

它確實(shí)比較好用,可以運(yùn)行在 Node 環(huán)境下。使用 JSDom,你可以不把 DOM 當(dāng)做 I/O 操作。這一點(diǎn)非常重要,因?yàn)橐?DOM 操作從前端代碼中分離出來(lái)非常困難(實(shí)際工作中幾乎不可能完全分離)。我猜 JSDom 的誕生就是因?yàn)檫@個(gè)原因:使得在 Node 中也可以運(yùn)行前端測(cè)試。

我們來(lái)看一下它的工作原理,和往常一樣,需要有初始化代碼和測(cè)試代碼。這次我們先看測(cè)試代碼。不過(guò)正式看代碼之前請(qǐng)先接受我的歉意。

四、歉意

這一部分是這個(gè)測(cè)試系列文章中唯一使用指定框架的部分,這部分使用的框架是 React。選擇 React 并不是因?yàn)樗亲詈玫目蚣?,我?jiān)定地認(rèn)為沒(méi)有所謂最好的框架,我甚至認(rèn)為對(duì)于指定的場(chǎng)景也沒(méi)有最好的框架。我相信的是對(duì)于個(gè)人來(lái)講,只有最合適,用著最順手的框架。

而我使用著最順手的框架就是 React,所以接下來(lái)的代碼都是 React 代碼。但是這里依然說(shuō)明一下,前端集成測(cè)試的 jsdom 解決方案可以適用于所有的主流框架。

ok,現(xiàn)在回到正題。

五、使用 Jsdom

  1. const React = require('react') 
  2.     const e = React.createElement 
  3.     const ReactDom = require('react-dom') 
  4.     const CalculatorApp = require('../../lib/calculator-app') 
  5.     ... 
  6.  
  7.     describe('calculator app component', function () { 
  8.     ... 
  9.       it('should work', function () { 
  10.         ReactDom.render(e(CalculatorApp), document.getElementById('container')) 
  11.  
  12.         const displayElement = document.querySelector('.display') 
  13.  
  14.         expect(displayElement.textContent).to.equal('0') 

注意看第 10 - 14 行,首先 render 了 CalculatorApp 組件,這個(gè)操作同時(shí)也 render 了 Display 和Keypad。第 12 和 14 行測(cè)試了 DOM 中計(jì)算器的顯示是否是 0(初始化狀態(tài)下)。

上面的代碼是可以運(yùn)行在 Node 下的,注意到里面用的是 document。我第一次使用它的時(shí)候特別驚訝。全局變量 document 是一個(gè)瀏覽器變量,竟然可以使用在 NodeJS 中。在這簡(jiǎn)單的幾行代碼背后有著大量的代碼支撐著,這些 jsdom 代碼幾乎是完美地實(shí)現(xiàn)了瀏覽器的功能。所以這里我要感謝 Domenic Denicola, Elijah Insua 和為這個(gè)工具包做過(guò)貢獻(xiàn)的人們。

使用 Jsdom

第 10 行中也使用了 document(調(diào)用 ReactDom 來(lái)渲染組件),在 ReactDom 經(jīng)常會(huì)使用它。那么在哪里創(chuàng)建的這些全局變量呢?在測(cè)試中創(chuàng)建的,見(jiàn)下面代碼:

  1. before(function () { 
  2.         global.document = jsdom(`<!doctype html><html><body><div id="container"/></div></body></html>`) 
  3.         global.window = document.defaultView 
  4.       }) 
  5.  
  6.     after(function () { 
  7.         delete global.window 
  8.         delete global.document 
  9.       }) 

代碼中創(chuàng)建了一個(gè)簡(jiǎn)單的 document,把我們的組件掛在一個(gè)簡(jiǎn)易 div 上。同時(shí)還創(chuàng)建了一個(gè) window,其實(shí)我們并不需要它,但是 React 需要。最后在 after 中清理全局變量。

document 和 window 一定要設(shè)置成全局的嗎?濫用全局變量不論理論和實(shí)踐的角度都不是個(gè)好習(xí)慣。如果它們是全局的,那這個(gè)集成測(cè)試就不能和其他的集成測(cè)試并行運(yùn)行(這里對(duì) ava 的用戶表示抱歉),因?yàn)樗鼈儠?huì)互相覆寫(xiě)全局變量,導(dǎo)致結(jié)果錯(cuò)誤。

然而,它們必須要設(shè)置成全局的,React 和 ReactDOM 要求 document 和 window 是全局的,不接受把他們以參數(shù)的形式傳遞。或許等 React fiber 出來(lái)就可以了?也許吧,不過(guò)現(xiàn)在我們還必須要把 document 和window 設(shè)置成全局的。

六、事件處理

剩下的測(cè)試代碼怎么寫(xiě)呢,看下面代碼:

  1. ReactDom.render(e(CalculatorApp), document.getElementById('container')) 
  2.  
  3.    const displayElement = document.querySelector('.display') 
  4.  
  5.    expect(displayElement.textContent).to.equal('0') 
  6.  
  7.    const digit4Element = document.querySelector('.digit-4') 
  8.    const digit2Element = document.querySelector('.digit-2') 
  9.    const operatorMultiply = document.querySelector('.operator-multiply') 
  10.    const operatorEquals = document.querySelector('.operator-equals') 
  11.  
  12.    digit4Element.click() 
  13.    digit2Element.click() 
  14.    operatorMultiply.click() 
  15.    digit2Element.click() 
  16.    operatorEquals.click() 
  17.  
  18.    expect(displayElement.textContent).to.equal('84') 

測(cè)試中主要實(shí)現(xiàn)的是用戶點(diǎn)擊 “42 * 2 = ”,結(jié)果應(yīng)該是輸出 “84”。這里獲取 element 使用的是廣為人知的querySelector 函數(shù),然后調(diào)用 click 點(diǎn)擊。還可以創(chuàng)建事件,然后手動(dòng)調(diào)度,見(jiàn)下面代碼:

  1. var ev = new Event("keyup", ...); 
  2.  document.dispatchEvent(ev); 

這里有內(nèi)置的 click 函數(shù),所以我們直接使用就好了。就是這么簡(jiǎn)單!

機(jī)智的你可能已經(jīng)發(fā)現(xiàn)了,這個(gè)測(cè)試和前面的端到端測(cè)試其實(shí)是一樣的。但是注意這個(gè)測(cè)試要快 10 倍以上,并且實(shí)際上它是同步的,代碼也更容易寫(xiě),可讀性也更好。

但是如果都一樣的話,那需要繼承測(cè)試干嘛?因?yàn)檫@是個(gè)示例項(xiàng)目嘛,并不是實(shí)際項(xiàng)目。這個(gè)項(xiàng)目里面只有兩個(gè)組件,所以端到端測(cè)試和繼承測(cè)試是一樣的。如果是在實(shí)際項(xiàng)目中,端到端測(cè)試可能包含了上百個(gè)單元,而繼承測(cè)試只包含少量單元,比如包含 10 個(gè)單元。所以實(shí)際項(xiàng)目中只有幾個(gè)端到端測(cè)試,而可能包含了上百個(gè)繼承測(cè)試。

七、總結(jié)

本文中主要介紹了什么:

  • 介紹了使用 jsdom 方便地創(chuàng)建全局變量 document 和 window;
  • 介紹了如何使用 jsdom 測(cè)試應(yīng)用;
  • 介紹了,測(cè)試就是這么簡(jiǎn)單。

點(diǎn)擊《測(cè)試你的前端代碼 - part4(集成測(cè)試)》閱讀原文。

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

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

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

2017-03-30 07:56:30

測(cè)試前端代碼

2017-09-14 15:16:56

2021-12-29 10:30:15

JMH代碼Java

2023-01-26 00:28:45

前端測(cè)試技術(shù)

2020-09-23 12:42:08

Linux

2020-09-15 06:15:23

滲透測(cè)試風(fēng)險(xiǎn)評(píng)估網(wǎng)絡(luò)安全

2020-09-11 11:29:34

滲透測(cè)試風(fēng)險(xiǎn)評(píng)估網(wǎng)絡(luò)安全

2020-10-13 10:51:10

Linux內(nèi)核

2023-10-27 08:49:00

JCovOpenJDK

2021-06-30 19:48:21

前端自動(dòng)化測(cè)試Vue 應(yīng)用

2021-10-29 05:53:51

前端測(cè)試開(kāi)發(fā)代碼

2020-10-12 10:22:16

Linux內(nèi)核

2024-10-22 15:14:16

2021-06-25 10:57:30

前端自動(dòng)化測(cè)試開(kāi)發(fā)

2020-10-10 10:14:42

Linux內(nèi)核

2021-06-26 07:40:21

前端自動(dòng)化測(cè)試Jest

2009-06-17 13:58:00

JMeter測(cè)試EJB

2014-05-07 09:52:35

測(cè)試測(cè)試人員

2024-09-30 08:01:44

2023-05-18 14:01:00

前端自動(dòng)化測(cè)試
點(diǎn)贊
收藏

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