相信有很多人遇到过这种情况,就是在入职公司后,开始接手公司的老项目,给公司的老项目修修改改。当我们在一个系统里边修改了很多代码时,但又不确定改动是否影响在核心逻辑时,是否会导致项目原来的功能出现bug时。我们就可以使用单元测试来帮助我们来进行测试。所以软件开发者编写单元测试,就成了很重要的事情。
单元测试框架的使用,让我们能够快速编写和自动执行我们的测试,并且将它们集成到我们的开发和部署过程中。
以下是一些常见编写测试的规范。
不要让你的单元测试过于复杂,本末倒置。尽量让你的单元测试代码简单明了,责任单一。
我们不仅仅要考虑函数正常运行时的情况,还要考虑函数错误运行时的情况。对代码进行单元测试,我们不仅仅要确保函数在输入正确的值时,有正确的输出,还要确保函数在输入错误参数时,运行的结果是失败的。这些对错误的检查更有利于我们预测引发错误的原因以及场景。
对功能逻辑复杂的函数,编写单元测试是十分困难的。我们要把复杂的函数拆分为相对较小的函数来进行单元测试。
单元测试应该是快速和轻量级的。但如果测试过程中涉及到网络数据的请求,或者对数据库的操作这就需要很长的时间来进行响应。这会使我们的单元测试变得很臃肿和重量级。但如果无法避免数据请求的话,我们一般会模拟请求结果来减轻我们的测试压力。
现在我们都已经对单元测试有了一定的了解了,那我们就着手开始编写我们的第一个单元测吧!!!
这次我将带着大家使用Mocha框架--市面上比较主流的测试框架之一。来编写我们的单元测试,虽然市面上每个框架都不同,但是他们大体是相似的。只要我们掌握了其中一种框架,其他的框架也能够很快的上手。
在编写单元测试之前,请确保你的电脑上已经安装的Node.JS环境。因为我们的Mocha
是运行在node
环境下的。所以我默认你的node环境已经安装好了。
首先创建了一个新的文件夹(必须是以英文命名) ,然后在文件夹里打开你的终端窗口或命令行窗口。然后输入npm init -y
。
然后你的项目里面就会生成一个package.json
文件
(我这里文件夹命名为UNIT-TEST)
然后我们就可以再在我们的项目里面安装Moche
框架了。在我们的终端窗口输入我们的npm install -D mocha
命令(如果安装速度慢的建议用cnpm)
然后打开我们的package.json
文件,把脚本里的test命令修改成mocha
这里我们编写一个简单的红绿灯系统,来用于我们待会的单元测试。
我们在项目中创建我们traffic,js
文件以及编写我们的TrafficLight
class TrafficLight {
constructor() {
// 对所有实例的lightIndex都赋值为0
this.lightIndex = 0;
}
// 定义我们的静态函数colors,只要一调用就返回函数
static get colors () {
return ["green", "yellow", "red"];
}
get light () {
return TrafficLight.colors[this.lightIndex];
}
next () {
this.lightIndex++;
// 这里故意设置了一个错误,this.lightIndex为3时是undefined
if (this.lightIndex > TrafficLight.colors.length) {
this.lightIndex = 0;
}
}
}
module.exports = TrafficLight;
TrafficLight.colors
:一个关于交通灯的颜色的数组常量。
lightIndex
:一个指示当前交通灯颜色的Index的变量。
light()
:一个返回当前交通灯颜色的函数。
next()
:一个改变当前交通灯颜色的函数,使交通灯指向下一个颜色。
首先,在项目文件夹中创建一个名为test
的文件夹。test
是Mocha
默认存放单元测试代码的文件夹。然后我们在test
项目下再新建一个traffic.test.js
文件来编写我们的单元测试
接下来开始编写我们的traffic.test.js
单元测试,首先导入我们的被测试的TrafficLight
模块。
const TrafficLight = require( "../traffic" );
我们还需要在代码中使用assert
模块进行测试,所以我们要导入assert
模块
const assert = require( "assert" );
在Mocha
中我们可以使用describe()
函数来帮我们进行单元测试的分组。所以我们应该先定义一个顶层分组。
describe( "TrafficLight", function () {
});
然后我们就可以在这个分组下进行一些子功能的测试定义与分组。首先我们先定义一个对colors
的测试。看colors
是否和我们预期的相同。
describe( "TrafficLight", function () {
describe( "colors", function () {
//测试内容
});
});
我们默认交通灯的colors
只是三种颜色green、yellow、red。所以我们可以去验证它的长度是否符合我们的要求。我们需要用到Mocha
框架里定义的it()
函数语法。它要编写在describe()
函数里。
describe( "TrafficLight", function () {
describe( "colors", function () {
it( "has 3 states", function () {
const traffic = new TrafficLight();
assert.equal( 3, TrafficLight.colors.length );
});
});
});
然后我们运行一下看是否能通过测试。我们在终端窗口运行npm test
,如果一切正确,Mocha 会打印出单元测试运行的结果。
运行通过,而且结构清晰
现在我们的项目已经可以正常运行我们的单元测试了,所以我们可以编写更多的测试用例。来测试我们的功能是否正常。
首先,我们可以在colors分组中添加一个对红绿灯颜色顺序是否正确的测试。
it( "colors are in order", function () {
const expectedLightOrder = [ "green", "yellow", "red" ];
const traffic = new TrafficLight();
for( let i = 0; i < expectedLightOrder.length; i++ ) {
assert.equal( expectedLightOrder[ i ], TrafficLight.colors[ i ] );
}
});
我们还可以对next()
函数进行测试,看他是否可能正确的改变红绿灯的颜色,使其按照正确的顺序执行。对next()
的测试不应该属于color分组。所以我们应该为它新建一个分组。并且在这个分组里编写两个测试,一个是测试交通灯的颜色是否按正确的顺序改变,一个是测试交通灯是否可以正确的循环执行。
describe( "next()", function () {
it( "changes lights in order", function () {
const traffic = new TrafficLight();
for( let i = 0; i < TrafficLight.colors.length; i++ ) {
assert.equal( traffic.light, TrafficLight.colors[ i ] );
traffic.next();
}
});
it( "loops back to green", function () {
const traffic = new TrafficLight();
// 颜色变化的循环顺序是 green -> yellow -> red -> green
for( let i = 0; i < 3; i++ ) {
traffic.next();
}
assert.equal( traffic.light, TrafficLight.colors[ 0 ] );
});
});
当我们运行单元测试时,我们可以看到有一个测试失败的提示。这因为我们在编写TrafficLight
类时,故意设置的一个错误,当this.lightIndex
为3时结果是undefined
。无法正确循环执行从red回到green
next () {
this.lightIndex++;
// 这里故意设置了一个错误,this.lightIndex为3时是undefined
if (this.lightIndex > TrafficLight.colors.length) {
this.lightIndex = 0;
}
那么其实修改这个错误也十分简单,我们只需要把我们的>
改为===
,当lightIndex
的值超过我们的color
数组长度时,它就会自动被赋值为0
,回到初始值。这样就可以使我们的代码正常执行。
if( this.lightIndex === TrafficLight.colors.length ){
this.lightIndex = 0;
}
单元测试的编写是比较简单的,它是提高我们软件开发的工具。它的使用有助于帮我更早的发现错误。并防止我们后期重构代码时再次产生同样的错误。它可以让我们的项目后期更易于管理和维护,即使我们的项目代码体积结构变得更大更复杂——尤其是在更大的开发团队中。而且自动化单元测试还能够让开发人员在够重构和优化代码时,不必担心新代码的是否会影响旧的功能。
单元测试是开发过程的关键部分,对于帮助您构建更好、更安全的 JavaScript 应用程序至关重要。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。