單元測試React

來源:互聯網
上載者:User

標籤:

React單元測試——十八般兵器齊上陣,環境構建篇

一個完整、優秀的項目往往離不開單元測試的環節,就 github 上的主流前端項目而言,基本都有相應的單元測試模組。

 

就 React 的項目來說,一套完整的單元測試能在在後續迭代更新中迴歸錯誤時候給與警示,但鑒於 React 本身的特殊性,我們又常常將其與 webpack 等工具相結合,其單元測試的部署相比常規的項目要折騰的多。

 

本文將作為 React 單元測試系列的開篇,和大家一同逐步構建其單元測試的環境。

 

你可以在我的倉庫下載到本文的樣本。

 

 

檔案組織和配置

 

1. 目錄結構

 

我們在項目根目錄下建立 src 和 test 檔案夾,前者用於存放我們編寫的各 React 組件模組,後者則用於存放對應單元測試模組。

 

接著我們需要一個最本質的 package.json 檔案,來描述項目的資訊跟相依模組,在根目錄執行

 
npm init
 

然後分部輸入相關資訊(你也可以先一路斷行符號,後續再修改),即可自動產生 package.json。

 

接著我們先通過 npm 安裝 React 所需的兩個模組—— react 及 react-dom:

 
npm install --save-dev react react-dom
 

這裡順便說一聲,React 在 v0.14 開始把 react 模組拆分成了上述的兩個包,其中 react 模組 中包含 React.createElement、React.createClass 等API,react-dom 模組中則包含 ReactDOM.render 等API(更具體的可以戳這裡瞭解)

 

安裝完成後根目錄會產生存放各 npm 模組的檔案夾 node_modules,我們此刻看到的目錄結構是這樣的,簡簡單單:

 

 

 

2. webpack 配置

 

我們打算隨主流以ES6的形式來書寫指令碼模組,同時新版的 React 也已經把 JSX 的轉換權移交給 babel 之類的工具,所以我們打算以 webpack 的形式來配置載入器跟打包。

 

如果你還不瞭解 webpack,請移步我的這篇入門文章。

 

先通過 npm 安裝 webpack(後續模組的安裝方式不再贅述):

 
npm install --save-dev webpack
 

我們要搭建一個極其簡單的測試環境,所以暫時只需用到一個很簡單的webpack配置,所以咱直接在根目錄下建立一個 webpack.config.js:

 
var webpack = require(‘webpack‘);module.exports = {    entry: undefined,    output: {        pathinfo: true    },    module: {        //載入器配置        loaders: [            { test: /\.js$/, loader: ‘babel-loader‘ }        ]    }};
 

注意我們打算對所有 .js 檔案配置一個 babel-loader 來轉換 JSX 跟 ES6,所以記得通過 npm 安裝上 babel-loader。

 

 

3. karma 配置

 

一個好的測試載入器能大大提升你的工作效率,而作為Angular團隊出品的 karma 是出眾的、最受歡迎的一款測試載入器,它有如下特點:

 
1. cli 運行,webstorm下配合完美 2. 良好支援 mocha、jasmine 等測試架構 3. 支援多瀏覽器的測試 4. 生態好,外掛程式多 5. 整合監控解放雙手,檔案變化時自動啟測,類似gulp的watch功能
 

要留意的是 karma 的安裝最好是以全域的形式來安裝,這樣才能確保正常使用 karma 的cli功能(我們後續將以karma XXX 的形式來執行測試)

 
npm install karma -g
 

接著我們在根目錄下建立 karma.conf.js 設定檔:

 
var isCI = process.env.CONTINUOUS_INTEGRATION === ‘true‘;var webpackConfig = require(‘./webpack.config.js‘);module.exports = function(config) {    config.set({        basePath: ‘‘,        files: [            ‘test/*.js‘        ],        preprocessors: {            ‘test/*.js‘: [‘webpack‘]        },        webpack: webpackConfig,        webpackMiddleware: {            noInfo: true        },        port: 9876,        colors: true,        autoWatch: true,        singleRun: isCI    });};
 

其中 isCI 變數用於判斷當前系統內容是否已預設支援持續整合(通過環境變數CONTINUOUS_INTEGRATION判斷,具體CI的變數名或值是什麼得依據具體情況來定,譬如 vuejs 中使用的是CI_PULL_REQUEST),若沒開啟CI則將 singleRun 設為false。

 

另外我們在 preprocessors 做了定義,要求執行 test 目錄下的指令碼時先通過 webpack 預先處理(轉JSX、ES6),並在 webpack 配置項設定其配置為我們之前建立的 webpack.config.js 。

 

 

我們打算使用 mocha 來作為單元測試的架構(當然你也可以使用 jasmine),然後使用 phantomjs 來作為測試瀏覽器引擎。

 

所以先通過 npm 包安裝好這倆個模組的 karma 外掛程式:

 
npm install --save-dev karma-mocha karma-phantomjs-launcher
 

然後我們進一步配置 karma.conf.js:

 
var isCI = process.env.CONTINUOUS_INTEGRATION === ‘true‘;var webpackConfig = require(‘./webpack.config.js‘);module.exports = function(config) {    config.set({        basePath: ‘‘,        frameworks: [            ‘mocha‘,  ‘phantomjs‘        ],        files: [            ‘test/*.js‘        ],        preprocessors: {            ‘test/*.js‘: [‘webpack‘]        },        webpack: webpackConfig,        webpackMiddleware: {            noInfo: true        },        port: 9876,        colors: true,        autoWatch: true,        browsers: [‘PhantomJS‘, ‘PhantomJS_custom‘],        customLaunchers: {  //自訂瀏覽器啟動器            ‘PhantomJS_custom‘: {                base: ‘PhantomJS‘,                options: {                    windowName: ‘my-window‘,                    settings: {                        webSecurityEnabled: false                    }                },                flags: [‘--load-images=true‘],                debug: true            }        },        phantomjsLauncher: {            // 資源(比如測試模組)出錯時依舊保持phantom不退出            exitOnResourceError: true        },        singleRun: isCI    });};
 

到了這一步,我們先假裝配置都已經折騰完畢了(其實還沒有),下面是新增測試模組

 

 

4. 建立測試模組

 

現在 src 目錄下還沒有任何 React 組件,我們建立一個 Alert.js:

 
import React from ‘react‘;const Alert = React.createClass({    render() {        return (            <div {...this.props}>                {this.props.children}            </div>        );    }});export default Alert;
 

接著在 test 目錄下新增一個 Alert.js 檔案,用於對上述的 src/Alert.js 組件進行簡單的單元測試:

 
import React from ‘react‘;import ReactTestUtils from ‘react/lib/ReactTestUtils‘;import Alert from ‘../src/Alert‘;describe(‘Alert‘, () => {    it(‘往頁面插入一段帶有strong標籤的組件‘, () => {        let instance = ReactTestUtils.renderIntoDocument(            <Alert>                <strong>Message</strong>            </Alert>        );        assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, ‘strong‘));    });});
 

如上述代碼所示,我們假設往<Alert>組件中放置了一個<strong>標籤並渲染到頁面上(這裡使用了 react/lib/ReactTestUtils 是我們下篇文章要介紹的東西)

 

於是我們斷言頁面上通過此形式所掛載上去的 Alert 組件裡肯定有一個 <strong> 標籤,如果找不到這個 <strong> 標籤則意味著該單元測試失敗。

 

現在我們似乎基本完成了全部的配置,執行 karma 啟動單元測試看一看:

 
karma start --browsers PhantomJS_custom
 

會發現報錯了:

 

 

這是 phantomJS 的一個坑導致的—— phantomJS 不支援 Function.prototype.bind ,詳情可見此issue。

 

解決方案也簡單,把 karma-phantomjs 替換為 karma-phantomjs-shim 即可。

 

通過 npm 安裝好 karma-phantomjs-shim 後我們修改 karma.conf.js 裡的 frameworks 配置項:

 
        frameworks: [            ‘mocha‘, ‘phantomjs-shim‘        ],
 

然後重新執行 karma,會發現繼續妥妥地報錯:

 

 

這是因為 karma 最終是將單元測試運行於一個用戶端瀏覽器中的,而不是node裡,而我們的測試模組又沒有 require(‘assert‘) 的引用,用戶端自然取不到assert對象了。

 

解決方案是使用 karma-chai,通過 npm 安裝後進一步修改 karma.conf.js 裡的 frameworks 配置項,加上 chai 外掛程式:

 
        frameworks: [            ‘mocha‘,  ‘chai‘,  ‘phantomjs-shim‘        ],
 

然後再執行 karma:

 

 

666的~ 到此為止我們的全部配置都折騰完畢。在後續可以使用此方案對 src 目錄下的全部組件進行簡單的單元測試~ 更多有趣的配置或工具我們在後續的文章再做介紹。

 

最後依舊提醒一下,本文的樣本可以從我的倉庫上下載到,有興趣的讀者可以下載了自行研究~ 共勉~

 

單元測試React

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.