前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为ES6配置JavaScript测试工具

为ES6配置JavaScript测试工具

作者头像
疯狂的技术宅
发布2019-03-27 16:02:20
2.9K0
发布2019-03-27 16:02:20
举报
文章被收录于专栏:京程一灯京程一灯

现在已经可以很方便的使用使用ES6(亦或是未来的ES7)了,你只需配置好Babel就可以开始编码。如果你只是在NodeJS环境中开发,你甚至都不需要Babel,因为NodeJS自带的ES6支持已经越来越好了。

针对开发流程的工作流是非常简单和详细的,那么针对测试的呢?你该如何为ES6代码编写单元测试呢?又该如何配置测试工具以支持这些新特性呢?

在本文中我会介绍如何配置那些最流行的测试工具 —— Mocha,Jasmine,Karma以及Testem —— 以便让它们能与ES6一起工作。我们还会看一看测试ES6代码的最佳实践。今后你就再也不用忽视对ES6代码的测试啦!

预备条件

在开始之前,我们需要先安装几个必要的工具:

  1. 我们需要Babel及相关的库来编译ES6代码
  2. 我们需要Webpack或是Browserify来打包模块

即使你的项目已经完成了这些步骤的配置,你还是需要查看以下的章节。某些测试工具可能会需要一些有可能被你遗漏的库。

安装Babel及相关库

不管你使用的是何种测试,打包工具,你都需要Babel和babel-polyfill。正如你可能知道的那样,Babel自身用来把ES6的新语法转变为旧的JavaScript引擎可以理解的格式,而babel-polyfill则会提供旧引擎中缺失的ES6对象(例如Promise)和函数(例如Array.prototype.find)。

npm install --save babel babel-polyfill

如果你打算测试Node.js代码, 你还需要安装babel-register。该模块可以让你选择的测试工具在加载模块时自动对模块进行编译。

npm install --save babel-register

你可能还要安装你需要的Babel presets,比如es2015和react。

npm install --save babel-preset-es2015 babel-preset-react

配置Babel

虽然你可以通过命令行参数或是写入package.json文件的方式传递Babel配置参数。但我还是推荐你使用一个.babelrc文件。

Babel会自动从.babelrc中加载配置。即使是你使用了一个调用了Babel的库,这也是适用的。把配置选项写入.babelrc文件意味着你不必在多处维护这些信息了。

以下是一个使用了es2015和react两个preset的.babelrc文件示例:

代码语言:javascript
复制
{
  "presets": ["es2015", "react"]
}
配置Webpack或Browserify

NodeJS用户请注意: 如果你只是想在Node环境进行测试,那么你可以跳过此章节直接去到讨论选择测试工具的章节。

Browserify用户需要安装babelify transform库。该库允许Browserify在构建过程中使用Babel对代码进行转译。

npm install --save babelify

你可以通过命令行参数传递给browserify:

browserify -t [ babelify ] some-file.js -o some-output-file.js

也可以写入package.json:

代码语言:javascript
复制
 "browserify": {
    "transform": ["babelify"]
  }

针对webpack,你需要安装babel-loader。webpack会利用该库对代码进行转译。

npm install --save babel-loader

然后在Webpack的配置文件中添加参数:

代码语言:javascript
复制
module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel'
    }
  ]
}

上边的配置会使用Babel转译node_modules目录以外,扩展名为.js.jsx的文件。排除模块目录可以显著的提高编译速度。

配置测试工具

在配置好了必要的预备条件之后,我们现在可以开始着手配置测试工具了。

接下来的部分我们会详细介绍如何配置各个工具。再之后,我们会着重介绍如何编写测试。

Mocha

在Node.js环境中你所要做的只是在执行Mocha时传入正确的参数:

mocha --compilers js:babel-register --require babel-polyfill

这会开启Babel对JavaScript文件的转译并会自动加载babel-polyfill模块。

整个命令对于手工输入来说有些太长了,你可以把它作为一个npm script加入到package.json中:

代码语言:javascript
复制
"scripts": {
    "test": "mocha --compilers js:babel-register --require babel-polyfill"
  }

需要注意的是Mocha默认会从test/目录加载测试用例。如果你希望从其它目录加载,你需要指定加载目录:

mocha --compilers js:babel-register --require babel-polyfill --recursive path/to/tests

在上例中我们使用--recursive参数用来保证即使测试用例存放在path/to/tests的子目录中也会被正确加载。

在浏览器环境中,你需要使用Webpack或是Browserify编译所有测试文件。

  • Browserify: browserify test/**/*.js -o tests-bundle.js
  • Webpack: webpack test/**/*.js tests-bundle.js

上面的命令会把test/目录中所有的JS文件打包到tests-bundle.js中。

然后在你执行测试的HTML文件中引入tests-bundle.js

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    <title>Mocha Tests</title>
    <link rel="stylesheet" href="node_modules/mocha/mocha.css">
  </head>
  <body>
    <div id="mocha"></div>
    `<script src="node_modules/mocha/mocha.js">`</script>
    `<script>mocha.setup('bdd')</script>`

    `<script src="tests-bundle.js">`</script>

    <script>
      mocha.run();
    </script>
  </body>
</html>

加载文件的先后顺序并不会影响测试,只要保证在mocha.run()语句执行前加载打包的测试文件即可。即使你在测试代码中使用require加载了任何断言库或是其它的工具库,在执行测试的HTML你都不必引入它们。

Jasmine

对Node.js环境来说,Jasmine并不是一个理想的选择。虽然它能工作,但是配置起来比Mocha要更复杂一些。

不像Mocha,Jasmine并没有提供命令行参数用于配置转译。因此我们需用通过babel-node来启动Jasmine。babel-node是针对node的一层包装,它会通过Babel执行你的代码。

为了更简单的使用Jasmine,我们把它安装到本地的node_modules目录:

npm install -g babel-cli npm install jasmine

为了让Jasmine正常工作,你需要先初始化它的配置文件:

node_modules/.bin/jasmine init

这会创建一个spec/support/jasmine.json文件。然后你就可以通过修改该文件来配置诸如测试文件路径之类的信息。

接下来就可以利用Babel执行我们的Jasmine测试代码了:

babel-node node_modules/.bin/jasmine

同样的,我们可以把它作为npm script写入package.json文件:

代码语言:javascript
复制
 "scripts": {
    "test": "babel-node node_modules/.bin/jasmine"
  }

在浏览器环境中,Jasmine的配置步骤和Mocha一样。使用你喜欢的打包工具将测试文件打包然后在测试执行文件中引入即可。

  • Browserify: browserify test/**/*.js -o tests-bundle.js
  • Webpack: webpack test/**/*.js tests-bundle.js

Karma

在使用Karma时,为了在浏览器中执行Babel转译过的测试,我们需要安装karma-babel预处理器模块。该模块会协助Karma使用Babel转译代码。

npm install karma-babel-preprocessor

一旦安装完成,你就可以在Karma配置文件中添加以下配置信息:

代码语言:javascript
复制
preprocessors: {
  "src/**/*.js": ["babel"],
  "test/**/*.js": ["babel"]
}

这将开启对src/目录以及test/目录下任何.js文件的Babel转译。

Testem

Testem针对ES6的配置很简单。你只需要在testem.json中添加以下配置:

代码语言:javascript
复制
 "serve_files": ["tests-bundle.js"],
 "before_tests": "browserify -t [ babelify ] test/**/*.js -o tests-bundle.js"

serve_files选项告诉testem需要发送给浏览器的额外的测试文件。由于我们使用了before_tests选项来把测试代码打包进tests-bundle.js,我们需要在serve_files中指定它。

或者是使用webpack:

代码语言:javascript
复制
 "serve_files": ["tests-bundle.js"],
  "before_tests": "webpack test/**/*.js tests-bundle.js"

为ES6代码编写单元测试

现在测试工具已经准备就绪了,让我们看看如何为ES6代码编写测试吧。以下的示例使用了Mocah和Chai,但原理同样适用于Jasmine。

基础

基本情况和测试非ES6代码时一样。我们使用describeit建立我们的测试用例,不同的是现在可以使用ES6的特性来优化我们的代码了。

创建一个名为test/的目录并创建一个包含以下内容名为test/arithmeticTest.js的文件:

代码语言:javascript
复制
const chai = require('chai').expect;

describe('Arithmetic', () => {
  it('should calculate 1 + 1 correctly', () => {
    const expectedResult = 2;

    expect(1 + 1).to.equal(expectedResult);
  });
});

上边的代码在测试中使用了ES6特性。在加载Chai时,我们使用了const而不是var。这意味着我们不会在不经意间重新定义该变量,并且它明确表明了我们不希望修改它的意图。

我们还使用了箭头函数。使用它,你可以在一定程度上简化代码,然而它也可能带来一些潜在的问题 —— 我会在后边的最佳实践章节讨论这一点。

最后,和加载Chai时一样,我们使用const声明了期望的结果变量。这同样可以避免问题,同时也表明了它的值不应被改变这一意图。

我们可以使用前文提到的命令执行这个测试:

mocha --compilers js:babel-register --require babel-polyfill

异步测试

通过传入回调函数done就可以使用箭头函数编写异步测试:

代码语言:javascript
复制
describe('Timeout', () => {
  it('should call the callback', (done) => {
    setTimeout(() => done(), 500);
  });
});

Mocha还自带Promise支持,这使得编写异步测试变得非常简单。我们会在最佳实践章节讨论这一点。

ES6 imports

在测试中使用ES6的import也是可行的。切记:测试代码也是代码。既然我们已经配置好了测试工具,任何在你应用中使用的特性也都可以在测试代码中使用。

代码语言:javascript
复制
import { expect } from 'chai';

describe('Arithmetic', () => {
  it('should calculate 1 + 1 correctly', () => {
    const expectedResult = 2;

    expect(1 + 1).to.equal(expectedResult);
  });
});

这和使用require的效果完全相同。

最佳实践

接下来让我们看一看一些针对ES6的最佳实践以及你可能会遇到的陷阱。

在Mocha中谨慎使用箭头函数

在Mocha中请谨慎使用箭头函数。在某些情况下你需要使用this.timeout来控制一个测试在超时之前的等待时间。如果你使用了箭头函数,那这个配置就不会生效。

出现这种情况的原因是箭头函数使用this的机制。这导致Mocha不能正确的绑定它的辅助方法。如果你用不到这些辅助方法,那么你可以放心的使用箭头函数。

避免在Sinon中使用箭头函数

与Mocha类似,在Sinon.js中使用箭头函数也可能导致问题。

问题出在sinon.test上。当你的测试中存在测试替身(test double)时使用它是个好主意,因为它会在测试结束时自动帮你释放被替身的对象。但是由于它使用了this绑定,因此它无法在使用箭头函数时正常工作。

解决方案是要么在使用sinon.test时避免使用箭头函数,要么通过beforeEachafterEach来手工初始化和释放测试替身:

代码语言:javascript
复制
var sandbox;
beforeEach(() => {
  sandbox = sinon.sandbox.create();
});

afterEach(() => {
  sandbox.restore();
});

it('should do something with a sandbox', () => {
  // 与sinon.test类似,这个stub会自动被清理
  var stub = sandbox.stub();
});
Mocha自带Promise支持

使用Mocha测试使用了ES6 Promise的代码就是小菜一碟。Mocha内置了对Promise的支持,因此你可以在一个测试中返回一个Promise。Mocha会帮你处理:

代码语言:javascript
复制
import { expect } from 'chai';

it('should succeed when promise is resolved', () => {
  const result = Promise.resolve('success');

  return result.then(function(value) {
    expect(value).to.equal('success');
  });
});

通常使用了Promise之后你需要编写异步测试。但是由于Mocha自带Promise支持,我们可以在测试中直接返回一个Promise,而Mocha会等待直到它被resolve。

当测试返回的Promise被reject时,Mocha也会很聪明的标记它为失败:

代码语言:javascript
复制
it('this test always fails', () => {
  return Promise.reject('error message');
});

要了解更多信息,请参考我的文章JavaScript单元测试中的Promise:权威指南。

如何测试ES6 generators?

Mocha支持Promise意味着当你需要测试带有Generator的代码时,你可以使用来自co模块的co.wrap方法。

npm install co

然后使用它包裹你的测试代码就可以了:

代码语言:javascript
复制
it('should do something with generators', co.wrap(function*() {
  var result = yield doSomeGeneratorThing();
}));
利用source maps

打包之后要调试你的代码可能会变得更加困难。由于打包后的文件包含了所有的代码,要想找到是哪个文件产生的问题变得很困难。

要解决这个问题,你可以在打包时开启source maps。

  • Browserify: 要在browserify中开启source maps,需要使用-d参数。例如: browserify -d -t [ babelify ] test/**/*.js -o tests-bundle.js
  • Webpack: 你可以通过在webpack配置文件中引入devtool: 'source-map'来开启source maps

在命令行中执行测试代码时,source maps是不必要的。

总结

测试ES6代码很简单,只需要给工具做一点点配置就可以了。在未来ES6得到更好的支持以后,你就可以摆脱这些配置了,除非你想通过Babel实现其它目的(比如支持ES7)。

使用ES6编写测试代码和不使用它时没什么两样。只要记住箭头函数可能导致的问题就行了。

那么你该使用那个工具呢?我推荐Mocha。由于内建了对Promise的支持,它对ES6测试的支持是最好的。同时它也可以很好的和现有库协同工作。


往期精选文章

ES6中一些超级好用的内置方法

浅谈web自适应

使用Three.js制作酷炫无比的无穷隧道特效

一个治愈JavaScript疲劳的学习计划

全栈工程师技能大全

WEB前端性能优化常见方法

一小时内搭建一个全栈Web应用框架

干货:CSS 专业技巧

四步实现React页面过渡动画效果

让你分分钟理解 JavaScript 闭包



小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 预备条件
    • 安装Babel及相关库
      • 配置Babel
        • 配置Webpack或Browserify
        • 配置测试工具
        • Mocha
        • Jasmine
        • Karma
        • Testem
        • 为ES6代码编写单元测试
          • 基础
            • 异步测试
              • ES6 imports
              • 最佳实践
                • 在Mocha中谨慎使用箭头函数
                  • 避免在Sinon中使用箭头函数
                    • Mocha自带Promise支持
                      • 如何测试ES6 generators?
                        • 利用source maps
                        • 总结
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档