如何用Mocha测试JavaScript - 第2部分
昨天我们学习了Mocha的基础知识。今天,我们会把Mocha整合到一个项目中,这样就可以看到它是如何实际工作的。
这个教程要讲什么?
本教程将提供如何使用Mocha进行测试的小型真实示例。到教程结束时,我们将成功使用Mocha测试现有的JS文件。在读本教程之前,应该先了解Mocha是什么,如何分组测试以及如何使用断言库。如果需要复习,请参阅我的第一篇Mocha教程。
项目设置
上一个教程中我们已经安装了Mocha。如果还没有的话,请通过执行$ npm install -g mocha
全局安装好Mocha。
接下来,我们要创建一个名为temperature
的项目目录。在temperature
目录中,我们将创建一个app.js
文件,以及一个名为 test
的文件夹。在test
文件夹中,创建一个名为test.js
的文件。最后,通过运行npm init
初始化项目。在项目初始化期间,最重要的问题是 'test command:',回答 'mocha' 就可。这样我们只需键入 npm test
就可以运行Mocha。
搞定后,应该有类似如下的文件结构:
temperature
|-- app.js
|-- package.json
|-- test
|-- test.js
package.json
文件还应包含以下json:
"scripts": {
"test": "mocha"
},
有了上面所有东西后,我们就可以开始了!
我们在测试什么?
我们将在本教程中测试我们的app.js
文件。为了加快进程,我已经写好了app.js
的内容。继续,将下面的代码复制到app.js
中:
cToF = function(celsius) {
if(!Number.isInteger(celsius)) return undefined;
return celsius * 9 / 5 + 32;
}
fToC = function(fahrenheit) {
if(!Number.isInteger(fahrenheit)) return undefined;
return (fahrenheit - 32) * 5 / 9;
}
我们的app.js
只有九行代码,由两个函数组成:
cToF()
- 是将摄氏温度转换为华氏温度的函数。它有一个参数,即摄氏温度,并返回对应的华氏温度。fToC() - 是相反的函数。它将华氏温度转为摄氏wen d。它的一个参数是华氏温度,并返回摄氏温度。
这两个函数最初都要检测确保它们被传递进来的参数是一个整数。如果不是整数(字符串、空白、
undefined
、NaN
等),则返回undefined
,函数短路。
设置测试
我们将测试以确保这些函数正常运行。这是我们的test.js
文件采用的结构:
一个名为
Temperature Conversion
的测试组在该测试组中,还有其它两个测试组,一个命名为
cToF
,一个命名为fToC
每个测试组将有三个测试用例:两个数字和一个非整数测试。
测试组
首先,我们用describe()
设置两个测试组:
var assert = require('assert');
describe('Temperature Conversion', function() {
describe('cToF', function() {
// tests here
});
describe('fToC', function() {
// tests here
});
});
上面,我们有两个嵌套的测试组,两个指定函数的describe
块在外部Temperature Conversion
的describe
块内。现在有了基本的结构,我们就可以给每个内部测试组添加三个it()
测试用例。
添加测试用例
三个测试用例都将使用内置的assert断言库。因为要测试相等性,所以我们要用assert.equal(actual,expected);
对于第一个测试,我们将测试一个应该保持不变的数字。如果你不知道的话,华氏温度和摄氏温度在零下40度是相等的。下面我们设置这个测试,以确保我们的函数正确处理数学:
it('should convert -40 celsius to -40 fahrenheit', function() {
assert.equal(-40, cToF(-40));
});
很棒!我们断言,一旦我们通过函数cToF
转换数字-40
,结果值也应等于-40
。
对于下一个测试,我们要看一下水的凝固点。我们想确保0摄氏度等于32华氏度。
it('should convert 0 celsius to 32 fahrenheit', function() {
assert.equal(32, cToF(0));
});
一切都和第一个测试一样,除了我们将数字0
传递到函数中,并期望结果等于32
。
对于最后一个测试,我们将测试一个空白字符串,并确保函数返回undefined
:
it('should return undefined if no temperature is input', function(){
assert.equal(undefined, cToF(''));
});
对于这个测试,我们期望cToF(' ')
的结果等于undefined
。
真棒,我们所有的cToF
测试都完成了!现在我们需要为函数fToC
做同样的事情。我不会带你去写这些测试 - 你现在应该能自己搞定。如下是它们应该看起来像的样子:
it('should convert -40 fahrenheit to -40 celsius', function() {
assert.equal(-40, fToC(-40));
});
it('should convert 32 fahrenheit to 0 celsius', function() {
assert.equal(0, fToC(32));
});
it('should return undefined if no temperature is input', function(){
assert.equal(undefined, convert.fToC(''));
});
我们完成了...对吧?
真棒,我们的测试设置完了,现在只需用npm test
运行即可:
0 passing (20ms)
哦豁。发生了什么事呢?
公开我们的函数
我们从未将我们的函数公开给Mocha。就是说test.js
文件没法与app.js
文件中的函数进行交互。幸运的是,有很多简单的方法可以做到这一点。
我们要创建一个名为convert的空对象
let convert = {};
我们要把每个函数变成新的convert对象上的一个方法,而不是两个不同的函数。
在
app.js
的末尾,我们要用module.exports
公开convert
对象。如果之前你从没用过module.exports
的话,它就是用来告诉JavaScript返回什么对象作为require
调用的结果。
下面我们研究一下代码,看看如何用它:
//app.js
let convert = {};
convert.cToF = function(celsius) {
if(!Number.isInteger(celsius)) return undefined;
return celsius * 9 / 5 + 32;
}
convert.fToC = function(fahrenheit) {
if(!Number.isInteger(fahrenheit)) return undefined;
return (fahrenheit - 32) * 5 / 9;
}
module.exports = convert;
现在要做的只是在test.js
中require
我们的app.js
文件,并且把测试中所用的函数名修改为包含convert
对象。如下是最终的test.js
代码:
//test.js
let convert = require('../app.js')
let assert = require('assert');
describe('Temperature Conversion', function() {
describe('cToF', function() {
it('should convert -40 celsius to -40 fahrenheit', function() {
assert.equal(-40, convert.cToF(-40));
});
it('should convert 0 celsius to 32 fahrenheit', function() {
assert.equal(32, convert.cToF(0));
});
it('should return undefined if no temperature is input', function() {
assert.equal(undefined, convert.cToF(''));
});
});
describe('fToC', function() {
it('should convert -40 fahrenheit to -40 celsius', function() {
assert.equal(-40, convert.fToC(-40));
});
it('should convert 32 fahrenheit to 0 celsius', function() {
assert.equal(0, convert.fToC(32));
});
it('should return undefined if no temperature is input', function() {
assert.equal(undefined, convert.fToC('a'));
});
});
});
运行测试
这次运行npm test
时,一切都按预期工作了!
Temperature Conversion
cToF
√ should convert -40 celsius to -40 fahrenheit
√ should convert 0 celsius to 32 fahrenheit
√ should return undefined if no temperature is input
fToC
√ should convert -40 fahrenheit to -40 celsius
√ should convert 32 fahrenheit to 0 celsius
√ should return undefined if no temperature is input
6 passing (34ms)
搞定
干的不错!现在我们在一个单独的文件中测试Mocha。还有更多的东西需要学习 - 去查看文档吧,现在应该有了需要理解它们所需的所有工具了。