UXCore 組件單測的一些事兒

UXCore 是 XUX 團隊開源的 PC 端 React UI 套件,做爲一個支持企業級應用的 React UI 開源套件,爲了保持項目的持續集成,良好的單元測試必不可少。本文來分享一下在編寫單元測試的過程當中遇到的一些問題和總結。javascript

在編寫單測的時候首先可能會遇到一個開發順序的問題,是先寫測試代碼仍是先寫程序代碼,那麼先來介紹兩種開發技術:BDDTDD。BDD 是行爲驅動開發,更趨向於需求,從寫單測的順序上能夠理解爲先了解行爲,而後去寫單測來檢測是否符合需求指望;TDD 是測試驅動開發,先編寫符合需求指望的測試,而後根據測試來實現最簡功能代碼,不斷進行迭代打磨代碼,在寫單測的順序上那就是先寫單測,根據單測來編寫功能代碼。這兩種開發技術分別適用於不一樣的場景,可根據本身的狀況來選擇使用。html

UXCore 目前已有的組件採用的是 BDD ,因爲組價代碼都已 ready 咱們就編寫測試來驗證需求是否已經知足,首先要作的就是通讀組件代碼(由於有的組件的做者不是本身),將其內部邏輯和實現要搞清楚,接下來纔會知道怎麼具體寫測試代碼!java

UXCore 組件單測環境

在編寫單測時咱們要將測試代碼運行起來,實時看到測試結果,而且要查看測試覆蓋率以更好的提升代碼質量,那麼這就須要測試運行器、測試框架等等工具或框架來支持,如下是 UXCore 組件採用的單測環境,其餘 React 項目也可參考使用。node

  1. 測試運行器(Test runner)主要負責測試的自動化,它能夠自動調起多種瀏覽器或者 js 環境讓你來調試測試代碼。目前有 JSTDKarmaTestSwarmBuster 等測試運行器,UXCore 使用的是 Karma ,緣由是它集成了 Istanbul 的 coverage 功能,可檢測測試覆蓋率,而且支持多種測試框架。在 uxcore-tools 中已經集成 karma ,你只需執行幾個命令就能夠。react

  2. 測試框架(Testing Framework),即運行測試的工具,測試框架規定了測試風格和測試的生命週期,經過測試框架爲程序添加測試,保證代碼質量。目前有 JasmineQunitSinonMocha 等測試框架。UXCore 選擇的是 Mocha ,它來自 TJ 大神,不但能夠在bash中進行測試,並且還擁有一整套命令對測試進行操做,Mocha 的異步測試作的比較好,在 it 的回調函數中會獲取一個參數 done ,類型是 function ,用於異步回調,當執行這個函數時就會繼續測試。jquery

  3. 固然,除了測試運行器 、測試框架以外咱們還須要斷言庫(Assertion library)來幫助咱們判斷代碼執行的正誤,比較流行的斷言庫有:expect.jsshouldchai,咱們使用的是 expect.js ,支持 IE6+ ,語法通俗易懂。git

  4. 在測試 react 組件時還要用到 React UI 測試庫,React 官方提供了工具庫,它對虛擬 DOM 和 真實 DOM 都有對應的測試方法,可是它使用起來不太方便。還有一個 Airbnb 公司的封裝的 Enzyme ,很是容易上手。咱們選擇的是後者。github

測試覆蓋率

測試覆蓋率是測試中的一種度量,描述源代碼被測試的比例和程度。經過測試覆蓋率能夠檢測哪些代碼沒有被測試,可是測試覆蓋率並不能做爲衡量代碼質量的標準和目標,而是一種發現未被測試代碼的手段。npm

覆蓋率的統計的核心思想就是,在源代碼對應的位置注入統計代碼,當代碼運行後,根據統計代碼統計的數據肯定程序運行的路徑,最終生成覆蓋率統計報告。整個過程能夠分爲三部分:轉換(instrument)、執行(run)、生成報告(report)。api

  1. 轉換(instrument)

    • 首先對源代碼進行語法分析生成語法樹

    • 在語法樹相應的位置注入統計代碼,在程序執行到這個位置的時候對相應的全局變量賦值,確保執行以後可以根據全局變量知道代碼的執行流程

    • 根據注入以後的語法樹生成對應的 JavaScript 代碼,即轉換以後的代碼(instrumented code)

注:這裏進行語法分析的好處是,針對書寫不規範的代碼(好比一行多個語句),依然可以很好統計出分支覆蓋和組合覆蓋等信息。反過來想,若是想要提升覆蓋率,那麼代碼要書寫規範。

  1. 執行(run)

這一步須要先載入轉換後的代碼:

  • 瀏覽器環境:須要將轉換後的代碼傳給瀏覽器。若是是 karma 之類的帶 server 的測試框架,須要經過 socket 傳輸至瀏覽器,執行完以後再將包含覆蓋率信息的執行結果傳回 server ,生成測試報告。

而後執行單元測試,產生的統計信息會掛在全局變量 this 下面。對於瀏覽器環境,this 就是 window。

  1. 生成報告(report)

這一步會根據全局標量中的覆蓋率信息生成特定格式的報告,如 html、lcov、cobertura、teamcity等。

想要了解更詳細的內容可移步:https://yq.aliyun.com/article...,若是想了解 Istanbul入門使用的童鞋能夠看一下阮大神的這篇。

如何編寫 React 組件單測

編寫單元測試就是用一段代碼來測試一個模塊或功能是否能達到預期結果的一個過程。

下邊列出兩個常見的例子給你們做爲參考:

  1. 最簡單的 props 測試。

    • 首先建立組件的真實 DOM 結構

    const wrapper = mount(<Select2 prefixCls="kuma-select2" ></Select2>);
    • 而後獲取到當前組件的 prefixCls props,用 enzyme 的 .props() API 就能夠很容易的取到 props 的值(這裏有一點要說明,.props() 只能取到 root component 的 props),而後用斷言句進行判斷當前的 prefixCls 是不是 'kuma-select2'

    expect(wrapper.props().prefixCls).to.equal('kuma-select2');
    • 完成上邊兩步就能夠了嗎?上邊只是 get props 符合了咱們的指望,那咱們再給組件更新一下 props 看會不會生效。enzyme 也提供了對應的 .setProps() 的 API ,真是太方便啦。而後再次驗證新的 prefixCls 有沒有更新。

    wrapper.setProps({ prefixCls: 'kuma-select2-test' });
    expect(wrapper.props().prefixCls).to.equal('kuma-select2-test');
  1. 模擬下拉框選中動做,測試 value 值是否已更新。

    • 首先仍是建立組件的真實 DOM 結構

    const wrapper = mount(<CascadeSelect options={options} />);
    • 而後要建立 Trigger 組件( dropdown的子組件 )的真實 DOM 結構,這裏要提一下 enzyme 的 .find() API ,它的參數除了能夠是選擇器外還能夠是子組件的名稱。

    const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
    • 接下來找到下拉選項中的第一項觸發 click 事件,.simulate() API 用來作事件綁定。

    dropdownWrapper.find('li').at(0).simulate('click');
    • 模擬完後就來驗證你要驗證的邏輯,獲取到子組件 CascadeSubmenu 的一項 option ,調用 CascadeSubmenu 的 props onItemClick 函數,將獲取到的 option 傳入進去,最後斷言句判斷最後組件的 value 是否不爲空。

    const option = dropdownWrapper.find('CascadeSubmenu').props().options[0];
    dropdownWrapper.find('CascadeSubmenu').props().onItemClick(option,2,false);
    expect(wrapper.state('value').length > 0).to.be.ok()

上邊的代碼使用了 Enzyme 的 Full DOM Rendering API ,首先建立 CascadeSelect 組件的真實 DOM 結構,而後再次建立 dropdown 的 Trigger 子組件的真實 DOM 結構,最後找到第一個選項觸發 click 事件。

Tip:若是組件引用了其餘的組件,那麼單測應該測到什麼程度呢?要不要測引用的其餘組件的代碼?答案就是:你不須要測試它引用的組件的代碼邏輯,引用組件的代碼測試會在它本身內部完成,固然你測了也不會提升覆蓋率,咱們只需測試咱們組件的代碼便可。

最後,怎麼能更加清晰的知道本身哪些代碼尚未覆蓋到呢?若是能夠看到就行了,可以對症下藥,絕對提升覆蓋率啊!固然,Karma 都幫你作好了,執行過 coverage 後會生成一個 coverage 目錄,它的 src 目錄下的組件文件命名的 html 文件打開後就會看到很是清晰的記錄,紅色的表示尚未覆蓋到的。固然也能夠本地起一個服務,可用 anywhere 直接瀏覽器裏查看覆蓋率列表和對應的詳細文件。下圖是一份coverage 報告。

相關文章
相關標籤/搜索