QUnit源码阅读(2):test基本执行流程
2014-02-17 16:02
471 查看
// 直接上代码 //step 1: write a simple test as the following. test("hello test", function() { ok(1 == "1", "Passed!"); }); //step 2: 调用test函数 QUnit = { //... test : function(testName, expected, callback, async) { //... //初始化test, test = new Test({ name : name, testName : testName, expected : expected, async : async, callback : callback, //回调函数, very important module : config.currentModule, moduleTestEnvironment : config.currentModuleTestEnvironment, stack : sourceFromStacktrace(2) }); if (!validTest(test)) { return; } test.queue(); }, //... } //step 3: 调用test.queue函数,在config.queue中存入test.init和queue的内置函数run。 Test.prototype = { //... queue : function() { var bad, test = this; synchronize(function() { test.init(); }); function run() { // each of these can by async synchronize(function() { test.setup(); }); synchronize(function() { test.run(); }); synchronize(function() { test.teardown(); }); synchronize(function() { test.finish(); }); } // `bad` initialized at top of scope // defer when previous test run passed, if storage is available bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-test-" + this.module + "-" + this.testName); if (bad) { run(); } else { synchronize(run, true); } } //... } //step 4.1 - 4.2 在config.queue中存入callback函数 function synchronize(callback, last) { config.queue.push(callback); if (config.autorun && !config.blocking) { process(last); } } //step 5 调用Qunit.start函数 QUnit.load = function() { runLoggingCallbacks("begin", QUnit, {}); //I do not care, right now //... QUnit.init(); //... if (config.autostart) { QUnit.start(); } }; //step 6, 调用 process(true) QUnit = { //... start : function(count) { config.semaphore -= count || 1; // don't start until equal number of stop-calls if (config.semaphore > 0) { return; } // ignore if start is called more often then stop if (config.semaphore < 0) { config.semaphore = 0; } // A slight delay, to avoid any current callbacks if (defined.setTimeout) { window.setTimeout(function() { if (config.semaphore > 0) { return; } if (config.timeout) { clearTimeout(config.timeout); } config.blocking = false; process(true); }, 13); //13ms后调用,即step 7 } else { config.blocking = false; process(true); } }, //... } //step 7: 调用 process(true) (function() { if (config.semaphore > 0) { return; } if (config.timeout) { clearTimeout(config.timeout); } config.blocking = false; process(true); //ref step 8 })() //step 8, 循环泵,整个test框架的调用驱动函数,将config.queue[]中的回调依次拿出来run //Attention: 利用函数window.setTimeout及next函数来不断循环的技巧☆☆☆ 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()(); //Attention, this is very important. } else { window.setTimeout(next, 13); //Or, 13ms 之后再次调用process(true). break; } } config.depth--; if (last && !config.blocking && !config.queue.length && config.depth === 0) { done(); } } //step 9, 调用init函数 Test.prototype = { //... init : function() { //... }, //... } //step 10. 调用run函数, 在 config.queue中放置更多的函数test.setup, run, teardown, finish Test.prototype = { //... queue : function() { //... function run() { // each of these can by async synchronize(function() { test.setup(); }); synchronize(function() { test.run(); }); synchronize(function() { test.teardown(); }); synchronize(function() { test.finish(); }); } //... } }; //step 11. 调用test.setup, run, teardown, finish Test.prototype = { //... setup : function() { //... }, run : function() { config.current = this; var running = id("qunit-testresult"); if (running) { running.innerHTML = "Running: <br/>" + this.name; } if (this.async) { QUnit.stop(); } //this.callback 将会调用我们在 step1中写的匿名函数function() { ok(1 == "1", "Passed!");}) //this.callback 的初始化请参考step2 if (config.notrycatch) { this.callback.call(this.testEnvironment, QUnit.assert); return; } try { this.callback.call(this.testEnvironment, QUnit.assert); } catch( e ) { QUnit.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + e.message, extractStacktrace(e, 0)); // else next test will carry the responsibility saveGlobal(); // Restart the tests if they're blocking if (config.blocking) { QUnit.start(); } } }, teardown : function() { //... }, finish : function() { //... }, }; //step 12: 调用 我们的测试函数 (function() { ok(1 == "1", "Passed!"); }); //step 13: ok函数 QUnit.assert = { /** * Asserts rough true-ish result. * @name ok * @function * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); */ ok : function(result, msg) { //... result = !!result; //... }, //... equal : function(actual, expected, message) { QUnit.push(expected == actual, actual, expected, message); }, } extend( QUnit, { //... push: function( result, actual, expected, message ) { //... message = escapeInnerText( message ) || ( result ? "okay" : "failed" ); //... }, //... });
相关文章推荐
- QUnit源码阅读(2):test基本执行流程
- QUnit源码阅读(3):asyncTest基本执行流程
- Google test源码阅读(一):基本执行流程
- Google test源码阅读(一):基本执行流程
- QUnit源码阅读(3):asyncTest基本执行流程
- Google test源码阅读(二):参数化测试执行流程
- Spark 源码阅读(1)——WordCount程序执行流程
- CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程
- CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程
- quartz 2.2.x 源码学习 基本执行流程分析
- Struts2源码阅读之Action和Interceptor的执行流程
- PHP yii 框架源码阅读(二) - 整体执行流程分析
- obs-studio源码阅读笔记:学习obs流程的第一步,test程序
- Yii源码阅读笔记 - 请求处理基本流程
- Mybatis执行dao接口方法的流程梳理及源码分析
- 10 DelayQueue 延时队列类——Live555源码阅读(一)基本组件类
- [Chrome源码阅读]Chrome启动代码流程3
- 14 BasicHashTable基本哈希表类(一)——Live555源码阅读(一)基本组件类
- Nginx源码分析—HTTP框架执行流程
- Junit-3.8.1源码分析02----具体分析(执行流程)