Why QUnit DO NOT QUALIFY
目录
1. WHAT - 测试工具 ⬆
-
- An easy-to-use JavaScript Unit Testing framework.
-
- DOM-less simple JavaScript testing framework
-
- Asynchronous BDD & continuous integration for node.js
-
- mocha - simple, flexible, fun javascript test framework for node.js & the browser. (BDD, TDD, QUnit styles via interfaces)
-
- Hiro is a framework for testing third-party JavaScript applications. It runs each test suite in a separate sandbox preventing global state leaks and conflicts.
- JsTestDriver
- JsTestDriver aims to help javascript developers use good TDD practices and aims to make writing unit tests as easy as what already exists today for java with JUnit.
-
- A powerful suite of automated test tools for JavaScript.
-
- Standalone and test framework agnostic JavaScript test spies, stubs and mocks.
2. WHAT - 什么是单元测试&自动化测试? ⬆
不用解释了吧。
3. WHAT - 为什么要做单元测试&自动化测试? ⬆
- 验证程序正确性
- 修复 bug 后的回归测试
- 安全的代码重构
- 缩短测试周期
4. HOW – Jasmine vs Qunit ⬆
4.1 基本结构 ⬆
- 测试套件&模块 suit
- 测试用例 case
- 断言 assertion
4.2 规范:CommonJS Unit Testing/1.1 ⬆
4.3 Jasmine ['dʒæzmɪn; 'dʒæs-] ⬆
- https://github.com/pivotal/jasmine
- http://pivotal.github.com/jasmine/
- https://github.com/mhevery/jasmine-node
Jasmine 是行为驱动的 JavaScript 测试框架。不依赖于任何第三方 JavaScript 框架。不需要 DOM。拥有干净、明确的语法,可以容易的编写测试用例。
-
优点:实现很完整,对于异步、同步测试的支持很好。
-
缺点:不符合规范,写法语义化导致繁琐,方法太多。
The Jasmine Ruby Gem is for Rails, Ruby, or Ruby-friendly development
4.4 基本语法 ⬆
describe("A suite", function() {
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
});
5. QUnit ⬆
QUnit 是一个强大、易用的 JavaScript 测试套件。它用于测试 jQuery 和插件,但是也适用于测试任何通用的 JavaScript 代码(甚至可用于服务端的 JavaScript 代码)。
- 优先:清晰、高质的源码;符合 CommonJS Unit Test 规范。
- 缺点:异步操作太繁琐(stop()、start())。
5.1 历史 ⬆
QUnit 最初作为 jQuery 的一部分,由 John Resig 开发。2008年有了自己的主页、名称、API 文档,允许作为其他 JavaScript 代码的单元测试工具,此时它仍然依赖于 jQuery。2009年重写,QUnit 完全独立运行。 QUnit 的断言方法遵从 CommonJS Unit Test 规范,该规范在某种程度上受到了 QUnit 的影响。
5.2 基本语法 ⬆
module( "group a" );
test( "a basic test example", function() {
ok( true, "this test is fine" );
});
test( "a basic test example 2", function() {
ok( true, "this test is fine" );
});
module( "group b" );
test( "a basic test example 3", function() {
ok( true, "this test is fine" );
});
test( "a basic test example 4", function() {
ok( true, "this test is fine" );
});
5.3 哪些开源库&框架在用 QUnit? ⬆
bootstrap、jquery、backbone、grunt ...
6. HOW - Demo ⬆
QUnit + jQuery Queue
7. HOW - 最佳实践 ⬆
- 测试粒度(覆盖率)足够细
- 按照业务模块组织测试代码
- 与业务代码分离
8. WHY - QUnit 实现原理 ⬆
-
初始化:用一个数组 config.queue 存放待执行的测试用例:
config = { queue: [], }; function synchronize( callback, last ) { config.queue.push( callback ); if ( config.autorun && !config.blocking ) { process( last ); } }
-
运行时:用一个 while 循环遍历数组 config.queue,从头部开始顺序执行:
function process( last ) { function next() { process( last ); } var start = new Date().getTime(); config.depth = config.depth ? config.depth + 1 : 1; while ( config.queue.length && !config.blocking ) { if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { config.queue.shift()(); } else { window.setTimeout( next, 13 ); break; } } config.depth--; if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { done(); } }
-
异步操作:调用 stop() 后设置 config.blocking = true;调用 start() 后设置 config.blocking = false。如果 config.blocking 为 true,则会每隔 13ms 尝试恢复 while 循环。