`
dengjianqiang200
  • 浏览: 128131 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

如何用Qunit测试你的JavaScript代码

阅读更多

原文地址:如何用Qunit测试你的JavaScript代码

 

QUnit, 由jquery团队开发,是一个对JavasScript进行单元测试的很好的框架。在这篇指南中, 我将具体介绍什么是Qunit,以及为什么你要关心严格地测试你的代码。

 

什么是QUnit

QUnit 是一个非常强大的javascript单元测试框架,可以帮你调试代码。它是由 jQuery 团队的成员写的,而且是jQuery的官方测试套装。但QUnit一般是足以测试任何常规javascript代码,它甚至可能通过一些javascript引擎比如Rhino或V8来测试服务器端JavaScript。

如果你不熟悉“单元测试”的概念,请不要担心。这不是很难理解的:

计算机编程中,单元测试(又称为模块测试)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

引自维奇百科。简单地说,你为你的代码的每个功能写测试,如果所有这些测试都通过了,那么你可以肯定的是,代码没有缺陷(通常,还是由你的测试有多彻底而定)。

为什么你要测试你的代码

如果你以前从未写过任何单元测试,你可能直接将你的代码上到网站上,点击一会看看是否有什么问题出现,并且尝试去解决你所发现的问题,采用这种方法会有很多的问题。

首先,这是很腻烦的。点击事实上并不是一件轻松的工作,因为你不得不确保每样东西都被点到而且很有可能你错过了一个或两个。

其 次,你为测试做的每件事情是不能复用的,这意味着它很难回归。什么是回归?想像一下你写了一些代码并测试,修复了所有你发现的缺陷,然后发布。此时,一个 用户发送了一些关于新缺陷的反馈,并且需要一些新功能。你返回到代码中,修复这些新缺陷并增加新功能。接下来可能会发生的就是一些旧的缺陷又重现了,这就 叫“回归”。看,现在你还得再去点击一遍,而且有可能你还找不到这些旧的担担缺陷;即使你这么做,这还需要一段时间才能弄清楚你的问题是由回归引起的。使 用单元测试,你写测试去发现缺陷,一旦代码被修改,您通过测试再筛选一次。如果回归出现,一些测试一定会失败,你可以很容易地认出他们,知道哪部分代码包 含了错误。既然你知道你刚才修改了什么,就可以很容易地解决。

另外一个单元测试的优点,尤其是对于web开发来说: 它使跨浏览器兼容性测试很容易。仅仅在不同浏览器中运行你的测试案例就行,如果一个浏览器出现问题,你修复它并重新运行这些测试案例,确保不会在别的浏览 器引起回归,一旦全部通过测试,你可以肯定的说,所有的目标浏览器都支持。

我想提及一个John Resig的项目:TestSwarm。 它将Javascript单元测试带到了一个新的层次,通过使其分布,这是一个网站,其中包含很多测试案例,任何人都可以去那运行一些测试案例,然后返回结果会返回到服务器。通过这种方式,代码会非常迅速的在不同的浏览器进行测试,甚至不同的平台运行。

如何用QUnit写单元测试

那么,你如何正确地用QUnit写单元测试呢?首先,您需要设置一个测试环境:

01 <!DOCTYPE html>
02 <html>
03 <head>
04     <title>QUnit Test Suite</title>
05     <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen">
06     <script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>
07     <!-- Your project file goes here -->
08     <script type="text/javascript" src="myProject.js"></script>
09     <!-- Your tests file goes here -->
10     <script type="text/javascript" src="myTests.js"></script>
11 </head>
12 <body>
13     <h1 id="qunit-header">QUnit Test Suite</h1>
14     <h2 id="qunit-banner"></h2>
15     <div id="qunit-testrunner-toolbar"></div>
16     <h2 id="qunit-userAgent"></h2>
17     <ol id="qunit-tests"></ol>
18 </body>
19 </html>

正如你所见,在这里使用了一个被托管的QUnit框架版本

将要被测试的代码已被添加到myProject.js中,而且你的测试应该插入到myTest.js。要运行这些测试,只需在一个浏览器中打开这个html文件。现在到了写些测试的时间了。

单元测试的基石是断主。

断言是一个命题,预测你的代码的返回结果。如果预测是假的,断言失败,你就知道出了问题。

运行断言,你应该把它们放入测试案例:

01 // Let's test this function
02 function isEven(val) {
03     return val % 2 === 0;
04 }
05  
06 test('isEven()', function() {
07     ok(isEven(0), 'Zero is an even number');
08     ok(isEven(2), 'So is two');
09     ok(isEven(-4), 'So is negative four');
10     ok(!isEven(1), 'One is not an even number');
11     ok(!isEven(-7), 'Neither is negative seven');
12 })

这里我们定义一个函数:isEven,用来检测一个数字是否为奇数,并且我们希望测试这个函数来确认它不会返回错误答案。

我们首先调用test(),它构建了一个测试案例;第一个参数是一个将被显示在结果中的字符串,第二个参数是包括我们断主的一个回调函数。

我们写了5个断言,所有的都是布尔型的。一个布尔型的断言,期望它的第一个参数为true。第二个参数依然是要显示在结果中的消息。

这里是你想要得到的,只要你运行测试:

a test for isEven()

由于所有的断言都已成功通过,我们可以高兴的认为isEven()工作正常。

让我们看看如果一个断言失败了会发生什么。

01 // Let's test this function
02 function isEven(val) {
03     return val % 2 === 0;
04 }
05  
06 test('isEven()', function() {
07     ok(isEven(0), 'Zero is an even number');
08     ok(isEven(2), 'So is two');
09     ok(isEven(-4), 'So is negative four');
10     ok(!isEven(1), 'One is not an even number');
11     ok(!isEven(-7), 'Neither does negative seven');
12  
13     // Fails
14     ok(isEven(3), 'Three is an even number');
15 })

这是结果:

a test contains failed assertion for isEven()

该断言失败因为我们故意把它写错,但是在你的项目中,如果测试未通过,并且所有的断言都是正确的,你将发现一个bug。

更多断言

ok()不仅是QUnit提供的唯一断言, 当在测试你的项目时,还会有一些非常有用的其他类型的断言:

比较断言

比较断言,equals(),期望它的第一个参数(是实际值)等于它的第二个参数(期望值)。它很类似于ok(),但均会输入实现和期望值,使得高度更加简单,像ok()一样,它可带一个可选的第三个参数作为显示的消息。

所以可以代替:

1 test('assertions', function() {
2     ok( 1 == 1, 'one equals one');
3 })
a boolean assertion

你可以这样写:

1 test('assertions', function() {
2     equals( 1, 1, 'one equals one');
3 })
a comparison assertion

注意最后一个“1”,这是比较值

如果两个值不相等:

1 test('assertions', function() {
2     equals( 2, 1, 'one equals one');
3 })
a failed comparison assertion

提供更多些信息,让生活更简单些。

比较断言使用“==”来比较它的参数,所以它不能处理数组或对象的比较:

1 test('test', function() {
2     equals( {}, {}, 'fails, these are different objects');
3     equals( {a: 1}, {a: 1} , 'fails');
4     equals( [], [], 'fails, there are different arrays');
5     equals( [1], [1], 'fails');
6 })

为了测试这种相等,QUnit提供了另外一种断言:恒等断言

恒等断言

恒等断言,same(),期望相同的参数相等,但是它较深的采用递归比较断言,不仅作用于原始类型,而且包括数组和对象。断言,在前面的例子中,如果你把他们改成恒等断言将全部通过。

1 test('test', function() {
2     same( {}, {}, 'passes, objects have the same content');
3     same( {a: 1}, {a: 1} , 'passes');
4     same( [], [], 'passes, arrays have the same content');
5     same( [1], [1], 'passes');
6 })

注意same()使用”===”去比较,如有必要的话,所以它在比较特殊值的时候就派上用场了。

1 test('test', function() {
2     equals( 0, false, 'true');
3     same( 0, false, 'false');
4     equals( null, undefined, 'true');
5     same( null, undefined, 'false');
6 })

结构化你的断言

把所有的断言放在一个单独的测试案例中是相当不好的想法,因为这很难去维护,并且不能返回一个纯净的结果。你需要做的就是结构化他们,把他们放在不同的测试案例,每个目标为一个单独功能。

你可以甚至通过调用模块函数来把测试案例组织到不同的模块:

1 module('Module A');
2 test('a test', function() {});
3 test('an another test', function() {});
4  
5 module('Module B');
6 test('a test', function() {});
7 test('an another test', function() {});
structure assertions

异步测试

在前面的示例中,所有的断言都是同步调用的,这意味着他们是一个接着一个运行的。在这个真实的世界,同样 存在着很多异步的函数,例如Ajax请求或通过setTimeout()或sestInterval()调用的方法。我们如何去测试这些种类的方法呢?QUnit提供了一个特殊的叫做和“异步测试”的测试案例,提供给异步的测试:

让我们首先尝试用常规的方法写:

1 test('asynchronous test', function() {
2     setTimeout(function() {
3         ok(true);
4     }, 100)
5 })
an incorrent example of asychronous test

看?这就好像我们没有写任何断言一样。这是因为断言是被异步执行的,到它被调用的时候,此次测试已经执行完成。

这是正确的版本:

01 test('asynchronous test', function() {
02     // Pause the test first
03     stop();
04  
05     setTimeout(function() {
06         ok(true);
07  
08         // After the assertion has been called,
09         // continue the test
10         start();
11     }, 100)
12 })
a correct example of asychronous test

在这,我们使用了stop()去暂停此次测试案例, 并且在断言被调用以后,我们使用start()继续。

在调用完test()后立即调用stop()是很平常的;所以QUnit提供了一个捷径:asyncTest()。你可以像这样重写之前的示例:

01 asyncTest('asynchronous test', function() {
02     // The test is automatically paused
03  
04     setTimeout(function() {
05         ok(true);
06  
07         // After the assertion has been called,
08         // continue the test
09         start();
10     }, 100)
11 })

还有一点要注意:setTimeout()通常会调用它自己的回调函数,但如果它是一个自定义的函数(例如:一个Ajax调用)。你如何确认回调函数被调用了呢?并且如果回调函数没有被调用,start()将不会被执行,整个单元测试将被挂起:

unit testing hangs

所以这就是你需要做的:

01 // A custom function
02 function ajax(successCallback) {
03     $.ajax({
04         url: 'server.php',
05         success: successCallback
06     });
07 }
08  
09 test('asynchronous test', function() {
10     // Pause the test, and fail it if start() isn't called after one second
11     stop(1000);
12  
13     ajax(function() {
14         // ...asynchronous assertions
15  
16         start();
17     })
18 })

你可以通过延时去stop(),它告知QUnit,“如果start()在延时后没有被调用,你应未通过测试”。你可以确认的是整个测试没有挂起而且如果哪里出了问题你可以注意到。

那么多个异步函数呢?你在哪里放置start()?可把它放在setTimeout()里:

01 // A custom function
02 function ajax(successCallback) {
03     $.ajax({
04         url: 'server.php',
05         success: successCallback
06     });
07 }
08  
09 test('asynchronous test', function() {
10     // Pause the test
11     stop();
12  
13     ajax(function() {
14         // ...asynchronous assertions
15     })
16  
17     ajax(function() {
18         // ...asynchronous assertions
19     })
20  
21     setTimeout(function() {
22         start();
23     }, 2000);
24 })

延时应该适当的长足够来允许二者的回调函数在测试继续执行前被调用。但是如果其中一个回调函数没有被调用怎么办?你怎样去知道?这就是expect()加入的原因:

01 // A custom function
02 function ajax(successCallback) {
03     $.ajax({
04         url: 'server.php',
05         success: successCallback
06     });
07 }
08  
09 test('asynchronous test', function() {
10     // Pause the test
11     stop();
12  
13     // Tell QUnit that you expect three assertions to run
14     expect(3);
15  
16     ajax(function() {
17         ok(true);
18     })
19  
20     ajax(function() {
21         ok(true);
22         ok(true);
23     })
24  
25     setTimeout(function() {
26         start();
27     }, 2000);
28 })

你给expect()传一个数字告知QUnit你期望X个断言去执行,如果一个断言未被执行,这个数字将不会匹配,而且你瘵会注意到有些东西出错了。

这仍有一个expect()的捷径:你只需给test()或asyncTest()的第二个参数传递一个数字:

01 // A custom function
02 function ajax(successCallback) {
03     $.ajax({
04         url: 'server.php',
05         success: successCallback
06     });
07 }
08  
09 // Tell QUnit that you expect three assertion to run
10 test('asynchronous test', 3, function() {
11     // Pause the test
12     stop();
13  
14     ajax(function() {
15         ok(true);
16     })
  • 大小: 27.8 KB
分享到:
评论
1 楼 dengjianqiang200 2011-03-31  
文章较长,代码较多,javaeye全贴不上来,只能贴部分的。。。

相关推荐

    如何用Qunit测试你的javascript代码文.pdf

    QUnit 是一个由 jQuery 团队开发的JavaScript单元测试框架,专为JavaScript代码的调试和测试设计。...通过编写和运行QUnit测试用例,开发者能够更加自信地进行代码修改和扩展,同时减少回归错误的可能性。

    如何用QUnit来测试JavaScript代码

    QUnit由jQuery团队成员编写,是jQuery的官方测试套件,不仅如此,QUnit还可以测试任何常规JavaScript代码,甚至可以通过一些像Rhino或者V8这样的JavaScript引擎,测试服务端JavaScript代码。如果不熟悉“单元测试”...

    qunit单元测试demo

    通过这个"qunit单元测试demo",开发者不仅可以学习到如何编写QUnit测试,还能理解单元测试在软件开发过程中的重要性,如何有效地测试和调试JavaScript代码,提高代码质量。对于想要提升JavaScript测试技能的人来说,...

    QUnit单元测试Demo

    3. **代码覆盖率**:虽然QUnit本身不支持代码覆盖率,但可以与其他工具(如Istanbul)结合,获取JavaScript代码的测试覆盖率报告。 4. **测试结果的TAP输出**:通过配置,QUnit可以输出TAP格式的结果,方便与持续...

    QUnit前台JS测试框架——实例

    QUnit是一款广泛应用于JavaScript开发中的单元测试框架,它是由jQuery项目的开发者们创建并维护的,旨在为JavaScript代码提供详尽的测试覆盖率。QUnit以其简洁的API和良好的可读性,成为了前端开发者进行代码质量...

    QUnit是Nodejs的一个单元测试框架

    在QUnit中,你可以为你的JavaScript代码创建测试套件(suites)和测试用例(cases)。测试用例包含了多个断言(assertions),这些断言会检查函数的输出是否符合预期。例如,你可以设置断言来验证函数返回的值是否...

    qunit代码和文档

    文档可能涵盖了单元测试的重要性,解释了如何设置QUnit测试环境,以及如何编写和运行测试用例。它可能还包含了QUnit的基本API,如`assert.ok()`, `assert.equal()`, `test()`, `module()`等,这些都是进行有效测试的...

    qunit 1.5 js 单元测试

    QUnit 的测试是基于HTML页面的,通过在页面上插入`&lt;script&gt;`标签引入QUnit库和待测试的JavaScript代码。每个测试用例都是一个独立的模块,使用`QUnit.module()`定义。在模块内部,可以使用`QUnit.test()`来创建具体...

    JavaScriptTestCode:使用 QUnit 等的 JavaScript 测试代码的集合。

    在这个名为"JavaScriptTestCode"的项目中,重点在于使用QUnit这样的JavaScript测试框架进行代码测试。 QUnit是jQuery基金会维护的一个强大的JavaScript单元测试框架。它被设计为开发者友好,易于使用,同时支持在...

    Javascript单元测试框架QUnitjs具体介绍_.docx

    QUnit 是一个强大的 JavaScript 单元测试框架,主要用于测试 JavaScript 代码的质量和功能。它由 jQuery 项目开发团队创建,因此对于 jQuery 生态系统来说,它是理想的测试工具,但同时也适用于任何其他 JavaScript ...

    Qunit 1.20

    它为JavaScript代码的测试提供了全面而严谨的解决方案,确保代码质量并减少软件缺陷。1.20版本是QUnit的一个重要里程碑,虽然官网访问可能有时会遇到速度问题,但这个版本的稳定性和测试覆盖能力依然非常出色。 ###...

    javascript测试.docx

    使用QUnit,可以轻松地编写测试用例,验证JavaScript代码的正确性。 YUI Test YUI Test是一个功能强大的JavaScript单元测试框架,由Yahoo!开发。YUI Test提供了一个完善的测试环境,支持异步测试、Mock对象等功能...

    testing:初学者如何用qunit测试网页的总结

    QUnit 是一个 javascript 框架,您可以在构建软件时使用它来测试软件。 学习如何使用 QUnit 以便您可以在构建软件时对其进行测试,从长远来看,这将节省您的时间。 测试将确保您只编写最少量的代码来让您的软件完成...

    Javascript单元测试框架QUnitjs详细介绍

    QUnit 是一个专门用于 JavaScript 代码的单元测试框架,由 jQuery 团队成员创建,同时也是 jQuery 的官方测试工具。虽然最初与 jQuery 相关,但 QUnit 可以应用于任何普通的 JavaScript 代码,甚至支持在服务器端 ...

    前端开源库-gulp-qunit-harness

    QUnit 支持异步测试,这对于处理事件驱动的JavaScript代码非常有用。 2. **Gulp 与 Gulp 插件** Gulp 是一个基于Node.js的任务管理工具,使用流(stream)模型处理文件,提高了构建速度。开发者可以定义一系列任务...

    JavaScript测试工具

    JavaScript测试工具是开发高质量JavaScript代码的关键组成部分,它们帮助开发者确保代码的正确性和稳定性。JavaScript作为一门广泛用于前端和后端开发的语言,其测试工具的丰富多样性使得开发者可以选择适合项目需求...

    javascript 测试工具

    JavaScript测试工具是开发高质量JavaScript代码的关键组成部分。它们帮助开发者确保代码的正确性和稳定性,通过自动化测试来找出潜在的错误和缺陷。在JavaScript的世界里,有许多优秀的测试框架和库可供选择,其中...

Global site tag (gtag.js) - Google Analytics
17