• 单元测试React


    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 目录下的全部组件进行简单的单元测试~ 更多有趣的配置或工具我们在后续的文章再做介绍。

     

    最后依旧提醒一下,本文的示例可以从我的仓库上下载到,有兴趣的读者可以下载了自行研究~ 共勉~

  • 相关阅读:
    流行技术博客站点收录
    session过期后自动跳转到登陆页
    《AngularJS》--指令的相互调用
    java socker编程
    20189307《网络攻防》第十一周作业
    20189307《网络攻防》第十周作业
    20189307《网络攻防》第九周作业
    20189307《网络攻防》第八周作业
    20189307《网络攻防》第七周作业
    20189307《网络攻防》第六周作业
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4928778.html
Copyright © 2020-2023  润新知