六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 67|回复: 0

QUnit源码阅读(2):test基本执行流程

[复制链接]

升级  92%

12

主题

12

主题

12

主题

童生

Rank: 1

积分
46
 楼主| 发表于 2012-12-22 21:28:46 | 显示全部楼层 |阅读模式
QUnit源码阅读(2):test基本执行流程

<div class="postText"><div id="cnblogs_post_body"><div class="cnblogs_code">// 直接上代码

//
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, finishTest.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, finishTest.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" );        //...            },    //... });
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表