[译] Cookbook of QUnit

本篇文章是QUnit的简介,可以作为很好的入门教程。文章原址

介绍

自动化测试时软件开发过程中必不可少的一部分,而单元测试则是自动化测试的最为基本的一块,软件的每一个组件,

每一个功能单元都需要经过不停地测试以保证在上线时可以正常的工作。当然,测试也不仅仅只有这些作用,最为人

所知的就是测试驱动设计(test-driven design),测试先于实现进行。先写出一个简单的测试,当然此时运行肯定会

出错,然后我们在开始完成具体的实现,直到测试通过。如果仅仅依靠我们自己实现测试函数,不仅仅难以抓住测试过程

中的各种细节(错误代码,错误位置,执行结果与预期结果差异),而且各个浏览器的兼容性也会让我们抓狂,所以我们

亟需一个解决浏览器差异性和提供详细信息的测试框架,John Resig大神写出了QUnit框架。我等凡人尽管写不出这种富有

调整型的框架,但是很有必要学会使用QUnit。

自动化单元测试

 问题

我们想对应用进行单元测试,或者也想从测试驱动设计获益,此时我们需要自己手动写测试函数。但是正如上文所提,测试

  细节信息和浏览器兼容性我们难以搞定,我们需要解决它。

 解决方案

  我们可以使用QUnit,在使用QUnit钱,需要引入qunit.js和qunit.css文件

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>QUnit basic example</title>
  <link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.16.0.css">
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <script src="//code.jquery.com/qunit/qunit-1.16.0.js"></script>
  <script>
    QUnit.test( "a basic test example", function( assert ) {
      var value = "hello";
      assert.equal( value, "hello", "We expect value to be hello" );
    });
  </script>
</body>
</html>

  id为qunit-fixture的div标签是必须的,在所有的QUnit测试中都是一样,它是测试夹具。每次测试完都会讲测试夹具内的

  内容清空。

  我们可以发现并没有在显示的在documentReady之后执行测试,这是因为测试器将会控制测试的开始执行时间,在执行QUnit.test

  时,将函数添加到一个等待队列中,知道测试器调用。

断言结果

  问题

   断言是单元测试必不可少的要素之一。使用者需要将预期的结果和让测试器执行具体实现的结果进行比对,并得出相应

  的判断。

  方案

   QUnit提供了简单的断言。

  ok( truthy [, message ] )

  最基本的断言就是ok(),它必须提供一个boolean参数(或者可以转化为boolean的参数,在js中貌似都可以类型转换为boolean),

  另外一个参数可选。

QUnit.test( "ok test", function( assert ) {
  assert.ok( true, "true succeeds" );
  assert.ok( "non-empty", "non-empty string succeeds" );
 
  assert.ok( false, "false fails" );
  assert.ok( 0, "0 fails" );
  assert.ok( NaN, "NaN fails" );
  assert.ok( "", "empty string fails" );
  assert.ok( null, "null fails" );
  assert.ok( undefined, "undefined fails" );
});

  equal( actual, expected [, message ] )

  equal用“==”操作符来比较actual和expected参数,message为测试通过显示的信息。

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( 0, false, "Zero, false; equal succeeds" );
 
  assert.equal( "three", 3, "Three, 3; equal fails" );
  assert.equal( null, false, "null, false; equal fails" );
});

  strictEqual()用“===”比较两个参数。

  deepEqual( actual, expected [, message ] )

  该方法对简单的数值类型也是使用“===”进行比较。而对于对象,则不是使用“===”。它会便利对象的属性,并比较键值对。

  (键和值都会比较)。

QUnit.test( "deepEqual test", function( assert ) {
  var obj = { foo: "bar" };
 
  assert.deepEqual( obj, { foo: "bar" }, "Two objects can be the same in value" );
});

同步回调

  问题

  在回调模式中,放在回调函数中的代码可能会阻止断言执行,所以需要通过某种方式提醒断言是否执行。

  方案

  我们可以使用assert.expect(n)来设定预期执行断言的数量。如果没有执行预期数量的断言,将会报错。

QUnit.test( "a test", function( assert ) {
  assert.expect( 2 );
 
  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 square equals 4" );
});

异步回调

  问题

   异步回调与测试器的队列和运行测试的方式有冲突。在该测试之后的测试函数将不会被执行。

  方案

  在异步回调中使用assert之后,调用assert.aysnc(),他会返回一个done函数,在测试执行完毕调用done函数。

  经过测试,如果不调用done函数,则末尾切片函数将不会被执行,之后的测试函数也不会被执行。

QUnit.test( "asynchronous test: async input focus", function( assert ) {
  var done = assert.async();
  var input = $( "#test-input" ).focus();
  setTimeout(function() {
    assert.equal( document.activeElement, input[0], "Input was focused" );
    done();
  });
});

测试的原子性

  在每次执行test之后,QUnit都会重置 #qunit-fixture的dom div,包括在内的事件。只要测试代码在测试夹具内,不用

  手动对夹具进行清理。

组测试

  组测试可以保证逻辑类似的测试在一起执行,而且可以添加切片函数。该函数在测试之前和之后执行。

QUnit.module( "module", {
  setup: function( assert ) {
    assert.ok( true, "one extra assert per test" );
  }, teardown: function( assert ) {
    assert.ok( true, "and one extra assert after each test" );
  }
});
QUnit.test( "test with setup and teardown", function() {
  assert.expect( 2 );
});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CaiRui

详细grep、sed、awk

[root@VM_0_7_centos tmp]# cat 1.txt 1 2 3 4 5 6 [root@VM_0_7_centos tmp]# cat 2...

4677
来自专栏数据派THU

独家 | 手把手教你如何用Python从PDF文件中导出数据(附链接)

有很多时候你会想用Python从PDF中提取数据,然后将其导出成其他格式。不幸的是,并没有多少Python包可以很好的执行这部分工作。在这篇贴子中,我们将探讨多...

1893
来自专栏linux驱动个人学习

Linux CFS调度器之虚拟时钟vruntime与调度延迟--Linux进程的管理与调度(二十六)

CFS为了实现公平,必须惩罚当前正在运行的进程,以使那些正在等待的进程下次被调度。

2094
来自专栏人人都是极客

环形缓冲区的实现

队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。

2634
来自专栏java一日一条

Github 的清点对象算法

这就叫”清点对象”(counting objects),Github需要实时计算出来,需要克隆的对象总数。

712
来自专栏深度学习那些事儿

提升python项目完成效率的调试方法技巧(上)

效率提升是极为重要的事情,我们的时间本来就不充裕,不应该过多将时间浪费在调试过程中。对于大型项目光有dubug是不够的,如果需要提高产品调试进度,必须需要采取一...

3957
来自专栏州的先生

对Python渗透测试探测器的改善

762
来自专栏Jerry的SAP技术分享

用代码判断当前系统是否支持某个版本的feature

JDK9已经出来有一段时间了,因此很多流行的Java应用纷纷增添了对JDK9乃至JDK10的支持,比如Tomcat。

1362
来自专栏AI研习社

开发、调试计算机视觉代码有哪些技巧?

在调试视觉代码时, 基本就是和多维数组打交道, 多维数组有很多的属性,打印起来比较麻烦。 boxx.loga 可以一次性展现出一个数组的大多数属性。

991
来自专栏游戏杂谈

Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题

主要用到协程(Coroutines)和游戏对象的生命周期(GameObject Lifecycle)基础知识,巧妙解决了游戏重启的问题。

3712

扫码关注云+社区

领取腾讯云代金券