jQuery做网站前端开发,功能开发完成后都是手动测试,想着是否可以学习一下jQuery的单元测试框架,以便后续在写jQuery的时候做一下单元测试,于是便学习了一个强大的jQuery单元测试框架。
一、简单使用
Qunit是由jQuery团队成员开发的一个强大的jQuery单元测试框架,目前已被广泛使用在各个项目中。为了使用Qunit,只需要在待测试的html页面中包含2个Qunit文件即可,分别为qunit.js和qunit.css文件。其中,qunit.js作为运行器和测试框架,而qunit.css作为测试套件的页面显示测试结果的样式。
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<!-- <meta name="viewport" content="width=device-width"> -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.6.0.css">
<script src="https://code.jquery.com/qunit/qunit-2.6.0.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
<script>
test("hello", function() {
ok(true, "world");
});
</script>
</html>
html页面中必须在<body>元素中放置一个id=“qunit”的元素。
运行该程序,在浏览器中看到的效果如下:
图1
头部显示测试套件的标题,若是绿色显示调,则表示全部通过,如图1所示,若至少有一个用例测试失败,则这个显示条会显示红色,如图2所示。图1中从上到下分别显示的是3个checkbox(在后续章节的调试工具里会具体介绍),浏览器的User-Agent信息以及总的测试信息,包括测试的时长,断言的总个数、断言成功的个数以及断言失败的个数。
如果测试失败会是什么情况呢?
我们对上面的代码做下修改,将函数ok()里的第一个参数改成false,如下所示:
ok(false, "world");
再次运行程序,在浏览器中看到的效果如下:
图2
上图中,给出了断言失败的错误信息,指出了断言失败的具体出错处。
二、断言
任何单元测试框架的必要元素就是断言,QUnit提供了大量的断言,大致可类如下:
图3
最基本的断言
ok()仅只有一个请求的参数,如果返回值为TRUE,这个断言就会通过,否则就失败。此外,还接受一个字符串类型的参数作为测试结果的显示。not()则与ok()相反,当参数为FALSE,这个断言就会通过。
基本对象比较
相比ok()与notOk(),equal()与notEqual()只能操作基本对象类型,效果等同js比较运算符==和!=,当测试结果为失败时,实际值和期望值都会显示在结果里,如下图所示。
QUnit.test( "equal test", function( assert ) {
assert.equal( 0, 0, "Zero, Zero; equal succeeds" );
assert.equal( "", 0, "Empty, Zero; equal succeeds" );
assert.equal( "", "", "Empty, Empty; equal succeeds" );
assert.equal( "three", 3, "Three, 3; equal fails" );
assert.equal( null, false, "null, false; equal fails" );
});
图4
深度比较
deepEqual()与notDeepEqual(),使用更加准确的比较运算符===,可以操作NaN,正则表达式,数组等类型。
比较对象属性
porpEqual(),使用更加精确的比较运算符===来比较对象的属性,不同于deepEqual(),这个断言可以用来比较拥有不同的构造函数和原型的两个对象。
回调
QUnit支持的回调断言包括同步回调和异步回调。
1)同步回调
有时候,我们在测试时,并不能确定回调会在什么时候能被真正调用。面对这种情况,我们可以使用expect()定义一个我们期望的回调个数,参数为3,实际上我们只定义了2个有回调的函数,运行程序,结果如图5所示,
QUnit.test( "a test", function( assert ) {
assert.expect( 3 );
function calc( x, operation ) {
return operation( x );
}
var result = calc( 2, function( x ) {
assert.ok( true, "calc() calls operation function" );
return x * x;
});
assert.equal( result, 4, "2 squared equals 4" );
});
图5
2)异步回调
使用assert.async()定义一个done函数,当操作结束的时候,调用done函数,完成对异步回调的测试。
QUnit.test( "assert.async() test", function( assert ) {
var done = assert.async();
var input = $( "#test-input" ).focus();
setTimeout(function() {
assert.equal( document.activeElement, input[0], "Input was focused" );
done();
});
});
三、分组
QUnit支持将用例进行分组,对测试用例分组后,我们便可以指定跑哪组用例,换个角度来说,也就是我们可以将我们经常用的测试用例进行模块封装,提高测试用例利用效率。
QUnit.module( "group a" );
QUnit.test( "a basic test example", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.test( "a basic test example 2", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.module( "group b" );
QUnit.test( "a basic test example 3", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.test( "a basic test example 4", function( assert ) {
assert.ok( true, "this test is fine" );
});
运行该程序,页面中会多出一个Module的下拉框,可以选中相应的测试用例组,进行测试。
图6
四、调试工具
Hide passed tests
选中这个checkbox,页面会隐藏通过的所有测试,当有大量的测试且只有少数测试失败的情况下,这个选项是挺有用的。此外,当我们选中这个checkbox后,点击Rerun按钮再次运行时,页面重新载入时只会测试上次未通过的测试。
Check for Globals
选中这个checkbox,QUnit会生成一个所有属性在window对象上的清单,在用例运行之前和之后会去检查差异。如果属性被增加或被删除了,测试就会失败并显示出差异。因此,这样可以帮助我们确保单元测试代码和项目代码在测试中不会因为暴露出来的全局变量而造成冲突。
No try-catch
选中这个checkbox,QUnit会在try-catch语句之外运行回调。若测试时抛出异常,测试就会停止。这样我们便可以直观的看到浏览器抛出的异常,更方便的追溯错误的代码。