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单元测试——十八般兵器齐上阵,环境构建篇的更多相关文章
- Maven系列第9篇:多环境构建支持,核心开发必备!
maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能. 这是maven系列第9篇. 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部 ...
- react 单元测试 (jest+enzyme)
为什么要做单元测试 作为一个前端工程师,我是很想去谢单元测试的,因为每天的需求很多,还要去编写测试代码,感觉时间都不够用了. 不过最近开发了一个比较复杂的项目,让我感觉一旦项目大了.复杂了,而且还是多 ...
- Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)
有公网环境的服务器可以直接看 Hyperledger Fabric 1.0 从零开始(二)--环境构建(公网) ,本篇内容与上篇相似,只不过环境搭建需要在内网下,也就是网络被限制的情况下. 1:环境构 ...
- Hyperledger Fabric 1.0 从零开始(二)——环境构建(公网)
1:环境构建 在本文中用到的宿主机环境是Centos ,版本为Centos.x86_647.2,通过Docker 容器来运行Fabric的节点,版本为v1.0.因此,启动Fabric网络中的节点需要先 ...
- SSM框架整合环境构建——基于Spring4和Mybatis3
目录 环境 配置说明 所需jar包 配置db.properties 配置log4j.properties 配置spring.xml 配置mybatis-spring.xml 配置springmvc.x ...
- React 与 Redux 在生产环境中的实践总结
React 与 Redux 在生产环境中的实践总结 前段时间使用 React 与 Redux 重构了我们360netlab 的 开放数据平台.现将其中一些技术实践经验总结如下: Universal 渲 ...
- Cocos2d-x v3.1 GUI系统--环境构建(七)
Cocos2d-x v3.1 GUI系统--环境构建(七) 在使用Cocos2d-x的GUI系统时,由于生成的工程默认是没有将GUI系统所需的库导入到项目的,所以我们必须把库导入到工程中并对工程做一些 ...
- 如何从零搭建一个webpack+react+redux+react-redux的开发环境一入门
阅读本文章的时候,你要有一定的基础知识储备,简单的es6知识,模块化思想知识,js基础知识,node基础知识,react等 首先执行npm init,此时我的文件叫case; 下面安装一些需要的npm ...
- jQuery2.x源码解析(构建篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...
随机推荐
- Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境
一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...
- Paypal开发中遇到请求被中止: 未能创建 SSL/TLS 安全通道及解决方案
最近在基于ASP.NET上开发了Paypal支付平台,在ASP.NET开发的过程中没有遇到这个问题,但是引用到MVC开发模式中的时候就出现了"未能创建 SSL/TLS 安全通道及解决方案&q ...
- RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密
最近换了一份工作,工作了大概一个多月了吧.差不多得有两个月没有更新博客了吧.在新公司自己写了一个iOS的比较通用的可以架构一个中型应用的不算是框架的一个结构,并已经投入使用.哈哈 说说文章标题的相关的 ...
- 那些年【深入.NET平台和C#编程】
一.深入.NET框架 1..NET框架具有两个组件:CLR(公共语言运行时)和FCL(框架类库),CLR是.NET框架的基础 2.框架核心类库: System.Collections.Generic: ...
- Exception in thread "main" java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.<init>(I)V
在学习CGlib动态代理时,遇到如下错误: Exception in thread "main" java.lang.NoSuchMethodError: org.objectwe ...
- 【干货分享】流程DEMO-合同会审表
流程名: 合同会审表 业务描述: 合同的审批及签订 流程相关文件: 流程包.xml 事务呈批表业务服务.xml 事务呈批表主数据.xml 流程说明: 1.此流程必须先进行事务呈批表流程的配置才可 ...
- Android local.properties 文件读取
转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6202369.html 本文出自[赵彦军的博客] 在Android Studio项目里面有个local.pro ...
- npm源切换
版权声明:欢迎转载,请附加转载来源:一路博客(http://www.16boke.com) 目录(?)[+] 安装 使用 列出可选的源 切换 增加源 删除源 测试速度 许可 项目主页 我们介绍 ...
- docker – 你应该知道的10件事
容器并不是一个全新的技术,但这并不妨碍Docker如风暴一样席卷整个世界. 如果你在IT圈里,你一定听说过Docker.就算与其他热门技术,如:Puppet/Chef,Hadoop或者MongoD ...
- 一条Sql语句分组排序并且限制显示的数据条数
如果我想得到这样一个结果集:分组排序,并且每组限定记录集的数量,用一条SQL语句能办到吗? 比如说,我想找出学生期末考试中,每科的前3名,并按成绩排序,只用一条SQL语句,该怎么写? 表[TScore ...