使用Qunit做javascript单元测试
2016-04-03 12:29
1196 查看
最近公司在搞敏捷开发,提倡拥抱变化,既然是变化,那就会出错咯,那怎么保证能及时发现代码中的错误呢?可以通过单元测试来保证代码执行的正确性,因此公司要求提交的代码必须有对应的单元测试,每次代码的提交都会跑一遍单元测试(服务端自动执行),也就是所谓的持续集成。
然后呢?那么然后?其实接下来就没有然后了,进度,进度,功能,功能,单元测试这东西就被抛到九霄云外了,但是自己借着这个机会了解了一下javascript的单元测试框架。自己主要了解了一下Qunit这个单元测试框架,类似的框架还有Jasmine,JsTestDriver,mocha,…,后面可以了解几个其他的框架,货比三家才能取长补短。
Hello world还是记忆中的味道。
我们引入了一个文件qunit.min.css以及qunit.min.js两个文件,这是Qunit所需要的js以及css。 还定义了一堆的div是用来输出结果的标记(
通过对比结果,我们可以得到下面的结论: euqal使用 “==” 进行比较 不能遍历对象的key进行比较,即如果比较对象不可使用equal进行比较 deepEqual 使用”===”进行比较 可以遍历对象的key进行比较 strictEqual 使用”===”进行比较, 不能遍历对象的key进行比较。 equal(), deepEqual(),strictEqual()他们几个还有几个相反意义的兄弟notEqual(), notDeepEqual(),notStrictEqual()。
throws()接受三个参数throws(block, expected, message)
block需要测试的函数
expected : Error Object (instance), Error Function (constructor), a RegExp that matches (or partially matches) the String //representation, or a callback Function that must return true to pass the assertion check。
message:输出信息
这个例子没啥意义,纯粹为了示例而示例,我们把控制台代开,可以看到’module setup’和’module teardown’分别被打印了两次。每个用例执行之前都会执行’setup()’,每个用例执行完成之后会执行teardown()方法。我们可以在setup以及teardown里面来做一些初始化的操作。
这里执行了一个setTimeout函数,test函数执行完之后,equal断言并没有执行,因此给了我们一个
相比上面的例子,在执行setTimeout之前,调用了一个stop函数告诉Qunit暂停执行测试,start()告诉Qunit恢复执行测试。
注意到上面的例子并没有
自定义断言其实就是一个普通的函数,addNumEqual接受四个参数,前两个相加和第三个对比,第四个为输出信息。
上面的例子戳这里Qunit DEMO
其他文章戳这里
然后呢?那么然后?其实接下来就没有然后了,进度,进度,功能,功能,单元测试这东西就被抛到九霄云外了,但是自己借着这个机会了解了一下javascript的单元测试框架。自己主要了解了一下Qunit这个单元测试框架,类似的框架还有Jasmine,JsTestDriver,mocha,…,后面可以了解几个其他的框架,货比三家才能取长补短。
Hello World开场
程序员写文章,必须用经典的Hello world开场镇楼。<!DOCTYPE html> <html> <head> <title></title> <link href="http://cdn.bootcss.com/qunit/1.18.0/qunit.min.css" rel="stylesheet"> <script src="http://cdn.bootcss.com/qunit/1.18.0/qunit.min.js"></script> </head> <body> <div id="qunit-fixture"></div> <div id="qunit-header">Qunit</div> <div id="qunit-filteredTest"></div> <div id="qunit-banner"></div> <div id="qunit-testrunner-toolbar"></div> <div id="qunit-userAgent"></div> <ol id="qunit-tests"></ol> <script type="text/javascript"> test('ok test', function(){ ok(true, 'hello world'); }) </script> </body> </html>
Hello world还是记忆中的味道。
我们引入了一个文件qunit.min.css以及qunit.min.js两个文件,这是Qunit所需要的js以及css。 还定义了一堆的div是用来输出结果的标记(
<ol id='qunit-tests'><ol>输出测试结果)。内联js代码执行了一个
test()函数,这里
test()定义了一个名字为ok test的测试用例,传给
test()的第二个参数为为测试真身。页面加载完毕之后就会执行
test()中的第二个参数。这里执行了一个
ok()方法,接受两个参数,第一个参数为boolean值,表示测试是否通过(为true则通过),第二个参数为输出信息,在测试执行通过的时候是输出。这里
ok()第一个参数为true,所以测试通过输出了我们熟悉的hello world。
Qunit提供的其他断言函数
除了上面提到的ok(),还有
equal(),
deepEqual(),
strictEqual(),
throws()等等,我们来一一说明。
equal(),
deepEqual(),
strictEqual()这三兄弟长得很像,都带有equal,显而易见的是用来比较是否相等的断言。他们有什么区别?用例子来说话。
Equal
test('equal test', function(){ //true equal(1, 1, ' 1 equal 1'); //true deepEqual(1, 1, '1 deepEqual 1'); //true strictEqual(1, 1, '1 strictEqual 1'); //true equal(1, '1', ' 1 equal "1" '); //false deepEqual(1, '1', '1 deepEqual "1"'); //false strictEqual(1, '1', '1 strictEqual "1"'); //false equal({a : 1}, {a : 1}, ' {a : 1} equal {a : 1} '); //true deepEqual({a : 1}, {a : 1}, '{a : 1} deepEqual {a : 1}'); //false strictEqual({a : 1}, {a : 1}, '{a : 1} strictEqual {a : 1}'); //true propEqual({a : {a : 1}}, {a : {a : 1}}, 'propEqual'); //propEqual和deepEqual有什么区别呢? })
通过对比结果,我们可以得到下面的结论: euqal使用 “==” 进行比较 不能遍历对象的key进行比较,即如果比较对象不可使用equal进行比较 deepEqual 使用”===”进行比较 可以遍历对象的key进行比较 strictEqual 使用”===”进行比较, 不能遍历对象的key进行比较。 equal(), deepEqual(),strictEqual()他们几个还有几个相反意义的兄弟notEqual(), notDeepEqual(),notStrictEqual()。
throws
test('throws', function(){ function CustomError(message){ this.message = message; } CustomError.prototype.toString = function(){ return this.message; } throws(function(){ throw 'error' }, "throw with just a message"); throws(function(){ throw new CustomError(); }, CustomError, 'raised error is an instance of CustomError'); throws(function(){ throw new CustomError('test') }, new CustomError('test'), 'raised error instance matches the CustomError instance'); throws(function(){ throw new CustomError('test') }, function(error){ return error.message == 'test'; }, 'raised error instance satisfies the callback function'); })
throws()接受三个参数throws(block, expected, message)
block需要测试的函数
expected : Error Object (instance), Error Function (constructor), a RegExp that matches (or partially matches) the String //representation, or a callback Function that must return true to pass the assertion check。
message:输出信息
module()
如果多个测试项,都需要执行相同的初始化步骤,我们可以把这些测试项放到同一个module下面。
module('module test', { setup : function(){ console.log('module setup'); }, teardown : function(){ console.log('module teardown'); } }); test('just a simple test in module test', function(){ ok(true, 'i am ok'); }); test('just a simple test in module test2', function(){ equal(1, 1, 'i am equal'); })
这个例子没啥意义,纯粹为了示例而示例,我们把控制台代开,可以看到’module setup’和’module teardown’分别被打印了两次。每个用例执行之前都会执行’setup()’,每个用例执行完成之后会执行teardown()方法。我们可以在setup以及teardown里面来做一些初始化的操作。
测试异步代码
代码是同步的时候,Qunit的单元测试从上到下执行不会有顺序的问题,但是碰到异步执行的javascript代码的时候,就需要告诉Qunit你先给我停住,我让你执行的时候你再执行。test('async', function(){ var a = ''; setTimeout(function(){ a = 1; equal(1, 1, 'i am equal'); }, 1000); }) test('i am just a simple test', function(){ ok(true, 'are you ok!'); })
这里执行了一个setTimeout函数,test函数执行完之后,equal断言并没有执行,因此给了我们一个
Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.错误提示。
test('async', function(){ var a = ''; stop(); setTimeout(function(){ a = 1; start(); equal(1, 1, 'i am equal'); }, 1000); })
相比上面的例子,在执行setTimeout之前,调用了一个stop函数告诉Qunit暂停执行测试,start()告诉Qunit恢复执行测试。
#####**asyncTest** asyncTest('asyncTest2', function(){ expect(2); setTimeout(function(){ ok(true, "asyncTest2"); ok(true, 'asyncTest2'); start(); }, 1000); })
注意到上面的例子并没有
stop()木有,注意到
asyncTest()替代了test()木有。asyncTest告诉Qunit这是一个异步测试,所以不需要调用
stop()。
expect(num)告诉qunit这个测试用例中预期执行num个用例,如果不够数或者多了就给你打大红叉叉。
自定义断言
Qunit给我们提供了一些常用的断言,ok(),
equal()等等,一些特殊业务我们需要自定义断言,qunit也是支持的。
//自定义断言,QUnit.push function addNumEqual(num, step, result, message){ var expected = num + step; var actual = result; QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); } test('self define assert method', function(){ addNumEqual(1,2,4,'wrong'); addNumEqual(1,2,3, 'right'); })
自定义断言其实就是一个普通的函数,addNumEqual接受四个参数,前两个相加和第三个对比,第四个为输出信息。
上面的例子戳这里Qunit DEMO
其他文章戳这里
相关文章推荐
- Cannot forward after response has beencommitted问题分析及解决
- 表单脚本
- js数据类型--对象&数组
- JavaScript深入理解函数参数列表及“不存在重载”
- 【笔记】 《js权威指南》- 第8章 函数 - 8.2 - 8.3 函数调用 实参 形参
- JavaScript常用对象Array(2)
- javascript入门
- jsp无法取到cookie问题及解决
- Javascript 构造函数、继承
- extjs4学习之配置
- js操作数组函数
- extjs4学习之配置
- [HeadFirst-JSPServlet学习笔记][第三章:实战MVC]
- [HeadFirst-JSPServlet学习笔记][第三章:实战MVC]
- [HeadFirst-JSPServlet学习笔记][第二章:高层概述]
- [HeadFirst-JSPServlet学习笔记][第二章:高层概述]
- [HeadFirst-JSPServlet学习笔记][第一章:前言与概述]
- [HeadFirst-JSPServlet学习笔记][第一章:前言与概述]
- js 实现表格的可编辑状态
- Javascript中最常用的55个经典技巧(转)