什么是单元测试
  每个单元测试就是一段用于测试一个模块或接口是否能达到预期结果的代码。

QUnitjs

概念
Qunit是一款强大的用于帮助调试代码的,JavaScript单元测试框架。是jQuery的官方测试套件,不仅如此,QUnit还可以测试任何常规JavaScript代码,甚至可以通过一些像Rhino或者V8这样的JavaScript引擎,测试服务端JavaScript代码。

[官网](http://qunitjs.com/)

开始: hello wolrd
1. 目前版本:2.0.1
2. 需要链接QUnit的js资源和css资源(可以npm下载,官网下载,链接静态资源)
3. 简单的测试案例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="node_modules/qunitjs/qunit/qunit.css">
<script src="node_modules/qunitjs/qunit/qunit.js"></script>
</head>
<body>
<!--页面输出标记-->
<h1 id="qunit-header">QUnit Hello World</h1>
<h2 id="qunit-banner"></h2>
<ol id="qunit-tests"></ol>
<script>
// 2.*
QUnit.test("hello", function(assert) {
assert.ok(true, "wolrd");
});
// 1.*
test("hello", function() {
ok(true, "wolrd");
});
</script>
</body>
</html>

  

4. 上述案例定义了一个名为hello的测试(test),在页面载入完毕的时候运行;test的第二个参数为测试函数;ok方法接收两个参数:第一个是表明测试是否通过,第二个是需要输出的信息。
5. 上述案例声明了两个版本的测试。2.*版本的全局方法test()被QUnit.test()替代,详细的版本语法区别见<http://qunitjs.com/upgrade-guide-2.x/>;

6. 效果图

二 HTML部分的标记
1. html部分

<body>
<!--页面输出标记-->
<h1 id="qunit-header">QUnit测试</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">
<input id="input" type="text" placeholder="placeholder text" />
</div>>
</body>

2. 效果图


3. toolbar调试工具
  1. Hide passed tests“隐藏通过的测试”,勾选后,通过的测试就不显示了。
  2. Check for Global “全局检测”。 如果勾选此项,在运行测试之前,QUnit会枚举window所有属性,然后与运行结束之后的window做比较,如果前后不一样,就会显示不通过-failed, 以及显示“引入或缺失全局属性”。**该工具作用在于可以很容易被发现判断导致全局变量的引入.**
  3. No try-catch "不要try-catch". **选中则意味着QUnit会在try-catch语句外运行回调,此时,如果测试出现异常,测试就会停止。**这有什么用呢?要知道,有些浏览器的调试工具是相当弱的,尤其IE6,一个未处理的异常要比捕获的异常可以提供更多的信息。即使再次抛出,由于JavaScript不擅长异常处理,原来的堆栈跟踪在大多数浏览器里都丢失了。
  4. toolbar的filter类似于搜索
  5. toolbar的Module可选择module
  6. (原子性)如果要测试DOM修改,我们可以使用***#qunit-fixture***元素。在做测试的时候,这个静态标记你**可以随便置空或append元素**,每个测试结束的时候QUnit会自动把**#qunit-fixture**元素的innerHTML属性值设置为初始值。如果可以使用jQuery,QUnit会使用jQuery的html()方法代替,同时清除jQuery事件句柄。

QUnit.module('qunit-fixture');
QUnit.test( "Appends a span", function( assert ) {
var fixture = $( "#qunit-fixture");
fixture.append( "<span>hello!</span>");
assert.equal( $( "span", fixture ).length, 1, "span added successfully!" );
});
QUnit.test( "Appends a span again", function( assert ) {
var fixture = $( "#qunit-fixture");
fixture.append("<span>hello!</span>");
assert.equal( $( "span", fixture ).length, 1, "span added successfully!" );
});

  

部分API  [详细文档](http://api.qunitjs.com/)

test
  1. module 分组

QUnit.module("M one",{
before: function(assert) {//在M one的第一个test前执行
console.log(assert);
},
after: function(assert) {//在M one的最后一个test后执行
console.log(assert);
}
});

  2. test

QUnit.test('test b', function(assert) {
  assert.ok(true, 'true is passed');
  assert.ok(1 ,"1 is passed");
  assert.ok(2, '2 is passed');
  assert.ok(new Object(), 'object is pass');
  assert.ok(2>1,'2>1 is passed');
  assert.ok(" ","' ' is passed");
  assert.ok([],'[] is passed');
});

在下一个module出来之前,M one之后的test都属于M one
Assert
  1. ok()上面已经提到
  2. equal()

function add (a,b) {
return a + b + 1;
}
QUnit.test("test a", function(assert) {
assert.ok(add(1,2) === 4, 'add is true');
assert.equal(add(1,2) , 4 , 'add is true');
});

接收三个参数,参数一与参数二相等则为true否则为false,参数三为输出信息.

  3. notEqual,deepEqual, notDeepEqual,strictEqual,notStrictEqual,propEqual,notPropEqual

QUnit.test('test-assert', function(assert) {
assert.equal(1,'1','相等');//将参一和参二进行比较(==) 相等则通过
assert.notEqual(1,2,'不相等');//不相等,则通过
assert.strictEqual(1,1,'全相等');//将参一和参二进行比较(===) 全相等则通过
assert.notStrictEqual(1,'1','不全相等');//不全相等则通过
assert.deepEqual({foo:1},{foo:'1'},'对象相等');//深度比较,如果是对象,则将值进行简单对比(相当于==),只有相等才能通过。
assert.notDeepEqual({foo:1},{foo:'2'},'对象不相等');
assert.propEqual({foo:1},{foo:1},'对象全等');//深度比较,如果是对象 则将值进行全等比较;
assert.notPropEqual({foo:1},{foo:'1'},'对象不全等');
});

notEqual: 将参一和参二进行比较(==) 不相等则通过

strictEqual: 将参一和参二进行比较(===) 全相等则通过
deepEqual: 深度比较,如果是对象,则将值进行简单对比(相当于==),只有相等才能通过
propEqual: 深度比较,如果是对象 则将值进行全等比较

4. expect()

QUnit.test("mulipile call done()",function(assert){
assert.expect(3);
assert.equal(1,'1','相等');
assert.notEqual(1,2,'不相等');
});
QUnit.test("mulipile call done()",function(assert){
assert.expect(3);
var done = assert.async(3);
setTimeout(function(){
assert.ok( true, "first call done." );
done();
},100);
setTimeout(function(){
assert.ok(true,"second call done");
done();
},300);
setTimeout(function(){
assert.ok(true,"third call done.");
done();
},200);
});

测试回调的时候,无论是不是异步,我们都不能确定回调会在某些时候被真正调用了。为了应付这种状况,可以使用expect(), 定义一个测试中我们**期望的判断个数**。这样就可以避免本应出现两个判别结果的,结果一个通过后就停止的情况。

Async Control

//模拟数据
Mock.mock('http://lhy', {
'name' : 'name@lhy',
'age|10-28': 20
});
//定义module
QUnit.module('m-ajax');
function ajax(successCallback) {
$.ajax({
url: 'http://lhy',
dataType: 'json',
success: function(data){
successCallback(data)
}
});
}
QUnit.test('test-ajax', function(assert) {
var done = assert.async();
var obj;
ajax(function(val){
obj = val;
console.log(val);
});
setTimeout(function(){
assert.ok(typeof obj === 'object','ajax返回的数据类型正确');
done();
},200);
});

也可以QUnit.start()与QUnit.stop()来控制异步回调中断言的判断。

callbacks
  1. begin()

QUnit.begin(function(tests){
  console.log(tests);
  console.log(tests.totalTests);
});

在所有test之前被调用一次。tests包括totalTests(test的数量)和modules(module的数组).

  2. done

QUnit.done(function( details ) {
console.log( "Total: ", details.total, " Failed: ", details.failed, " Passed: ", details.passed, " Runtime: ", details.runtime );
});

在test结束之后调用,details包括failed(失败的断言数),total(总断言数),passed(通过的断言数),runtime(所有test执行完所用的时间)

Configuration and Utilities
  assert 断言

自定义判断
  1. 定义

QUnit.assert.mod2 = function(value, expected,message) {
  var actual = value % 2;
  this.push(actual === expected ,actual ,expected,message);
}; 

2. 使用

QUnit.test("mod2",function(assert) {
  assert.expect(2);
  assert.mod2(2, 0, "2 % 2 == 0");
  assert.mod2(3, 1, "3 % 2 == 1");
});

example:判断设备

//判断是否是pc
function IsPC() {
  var userAgentInfo = navigator.userAgent;
  var Agents = new Array("Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod");
  var flag = true;
  for (var v = 0; v < Agents.length; v++) {
    if (userAgentInfo.indexOf(Agents[v]) > 0) {
      flag = false;
      break;
    }
  }
  return flag;
}
//判断是Android还是iOS
function getOSType() {
  if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
    return "IOS";
  } else if (/(Android)/i.test(navigator.userAgent)) {
    return "Android";
  } else {
    return "other";
  }
}
QUnit.module("M one");
  QUnit.test('test-device', function(assert) {
  assert.ok(IsPC(), 'this is PC');
  assert.ok(getOSType()=='Android', 'this is Android');
});  

PC运行截图:

Android端运行截图:

QUnit使用的更多相关文章

  1. qunit 前端脚本测试用例

    首先引用qunit 测试框架文件 <link rel="stylesheet" href="qunit-1.22.0.css"> <scrip ...

  2. Cookbook of QUnit

    本篇文章是QUnit的简介,可以作为很好的入门教程.文章原址 介绍 自动化测试时软件开发过程中必不可少的一部分,而单元测试则是自动化测试的最为基本的一块,软件的每一个组件, 每一个功能单元都需要经过不 ...

  3. 使用QUnit进行自动化单元测试

    前言 前阵子由于项目需求接触了java的单元测试JUnit,就顺带着学习了前端的单元测试:Qunit. 既然跟测试有关,不妨介绍一下测试中的黑盒测试.白盒测试以及单元测试. 1.黑盒测试:所谓的黑盒, ...

  4. JavaScript测试工具比较: QUnit, Jasmine, and Mocha

    1. QUnit A JavaScript Unit Testing framework. QUnit is a powerful, easy-to-use JavaScript unit testi ...

  5. 在requirejs中使用qunit

    requirejs(['QUnit'], function(qunit) { qunit.test('test name', function(assert) { // 一些测试, assert }) ...

  6. Javascript单元测试之QUnit

    首先去Qunit官网下载. Qunit有一个js脚本文件和一个css我们在页面中引入它. <script src="qunit-2.0.1.js"></scrip ...

  7. Javascript单元测试Unit Testing之QUnit

    body{ font: 16px/1.5em 微软雅黑,arial,verdana,helvetica,sans-serif; }           QUnit是一个基于JQuery的单元测试Uni ...

  8. qunit学习(一)

    QUnit是一个强大的JavaScript单元测试框架,用于调试代码.该框架是由jQuery团队的成员所开发,并且是jQuery的官方测试套件.任意正规JavaScript代码QUnit都能测试. 其 ...

  9. QUnit使用笔记-5简化编写

    在测试中,如果用到了大量相同的方法返回判断结果,可以将他们简化; 使用push(): push( result/*boolean,result of assert*/, actual, /*objec ...

  10. QUnit使用笔记-4保持原子性与分组

    原子性: 当将许多测试用例放到一起测试的时候,可能会因为相互的副作用而出错:这个时候应该尽可能将他们分别放到test()中测试: 对应测试到Dom,应该尽可能地使用#qunit-fixture,因为它 ...

随机推荐

  1. Java 面试题基础概念收集(高级)

    JVM垃圾回收: GC又分为 minor GC 和 Full GC (也称为 Major GC ).Java 堆内存分为新生代和老年代,新生代中又分为1个 Eden 区域 和两个 Survivor 区 ...

  2. PHP设计模式(二):工厂方法模式

  3. Graph_Master(连通分量_Poj_1904)

    Poj_1904 背景:本来是在做Voj的连通分量,做到了E( hdu_4685 ),想到了二分图,但是笔者只会最大匹配,但题目要求要输出所有的最大匹配情况,想了好久都没想出来怎么做,因为如果我已知一 ...

  4. JVM 内存调优 与 实际案例

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  5. python 使用set对list去重,并保持list原来顺序

    list_one=re.findall(r"^\s{0}[A-Za-z]*\b", txt,re.M) #匹配一级目录 addr_to = list(set(list_one))a ...

  6. checkbox及css实现点击下拉菜单

    面试遇到的问题.用checkbox中的:checked伪类选择器实现. 通过label标签来触发checkbox的unchecked 和checked两种状态:用css普通同胞选择器 ~.另外补充一点 ...

  7. .Net Core 二级域名绑定到指定的控制器

    在说二级域名绑定之前,先说一下.net core中的区域,关于区域这一块儿在很久之前的博客中,已经提过,详见<03-dotnet core创建区域[Areas]及后台搭建>,在这篇博客中, ...

  8. 项目使用文档管理:MediaWiki安装及使用入门

    MediaWiki是著名的开源wiki引擎,全球最大的wiki项目维基百科(百科词条协作系统)是使用MediaWiki的成功范例,MediaWiki的最大作用在于对知识的归档,可用于构建企业/个人知识 ...

  9. 页面title加icon

    把favicon.ico放入根目录下,在head中添加一下代码 <link rel="icon" type="image/x-icon" href=&qu ...

  10. hdu4318阶梯博弈nim变形

    阶梯博弈原理参考:http://www.cnblogs.com/jiangjing/p/3849284.html 这题计算每两个之间的间隔就行了,如果是奇数个就把第一个前面的看作一个,偶数个就是两个点 ...