Home page Forum Wiki Mail Jabber Devel NIX-FILES

AltLUG Git

Git-repositories of Altai Linux User Group

Fixes #344 - Capture and show test duration.
authorRichard Gibson <richard.gibson@gmail.com>
Sat, 3 Nov 2012 16:43:30 +0000 (12:43 -0400)
committerJörn Zaefferer <joern.zaefferer@gmail.com>
Sat, 17 Nov 2012 14:47:49 +0000 (15:47 +0100)
qunit/qunit.css
qunit/qunit.js
test/logs.js
test/test.js

index 552c94c..a0efe39 100644 (file)
        color: #000;
 }
 
+#qunit-tests li .runtime {
+       float: right;
+       font-size: smaller;
+}
+
 .qunit-assert-list {
        margin-top: 0.5em;
        padding: 0.5em;
index cfefe14..796923a 100644 (file)
@@ -113,6 +113,7 @@ Test.prototype = {
                        teardown: function() {}
                }, this.moduleTestEnvironment );
 
+               this.started = +new Date();
                runLoggingCallbacks( "testStart", QUnit, {
                        name: this.testName,
                        module: this.module
@@ -148,14 +149,20 @@ Test.prototype = {
                        QUnit.stop();
                }
 
+               this.callbackStarted = +new Date();
+
                if ( config.notrycatch ) {
                        this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
                        return;
                }
 
                try {
                        this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
                } catch( e ) {
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+
                        QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
                        // else next test will carry the responsibility
                        saveGlobal();
@@ -169,6 +176,9 @@ Test.prototype = {
        teardown: function() {
                config.current = this;
                if ( config.notrycatch ) {
+                       if ( typeof this.callbackRuntime === "undefined" ) {
+                               this.callbackRuntime = +new Date() - this.callbackStarted;
+                       }
                        this.testEnvironment.teardown.call( this.testEnvironment );
                        return;
                } else {
@@ -190,12 +200,13 @@ Test.prototype = {
                        QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
                }
 
-               var assertion, a, b, i, li, ol,
+               var i, assertion, a, b, time, li, ol,
                        test = this,
                        good = 0,
                        bad = 0,
                        tests = id( "qunit-tests" );
 
+               this.runtime = +new Date() - this.started;
                config.stats.all += this.assertions.length;
                config.moduleStats.all += this.assertions.length;
 
@@ -238,7 +249,7 @@ Test.prototype = {
                        b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
 
                        addEvent(b, "click", function() {
-                               var next = b.nextSibling.nextSibling,
+                               var next = b.parentNode.lastChild,
                                        collapsed = hasClass( next, "qunit-collapsed" );
                                ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
                        });
@@ -253,13 +264,19 @@ Test.prototype = {
                                }
                        });
 
+                       // `time` initialized at top of scope
+                       time = document.createElement( "span" );
+                       time.className = "runtime";
+                       time.innerHTML = this.runtime + " ms";
+
                        // `li` initialized at top of scope
                        li = id( this.id );
                        li.className = bad ? "fail" : "pass";
                        li.removeChild( li.firstChild );
                        a = li.firstChild;
                        li.appendChild( b );
-                       li.appendChild ( a );
+                       li.appendChild( a );
+                       li.appendChild( time );
                        li.appendChild( ol );
 
                } else {
@@ -277,7 +294,8 @@ Test.prototype = {
                        module: this.module,
                        failed: bad,
                        passed: this.assertions.length - bad,
-                       total: this.assertions.length
+                       total: this.assertions.length,
+                       duration: this.runtime
                });
 
                QUnit.reset();
@@ -963,7 +981,7 @@ extend( QUnit.constructor.prototype, {
        // testStart: { name }
        testStart: registerLoggingCallback( "testStart" ),
 
-       // testDone: { name, failed, passed, total }
+       // testDone: { name, failed, passed, total, duration }
        testDone: registerLoggingCallback( "testDone" ),
 
        // moduleStart: { name }
index f763c20..afec437 100644 (file)
@@ -38,131 +38,122 @@ QUnit.log(function(context) {
        logContext = context;
 });
 
-(function () {
-       function createCallback(logType) {
-               QUnit[logType](function () {
-                       console.log(logType, arguments);
-               });
-       }
-
-       var logs = ["begin", "testStart", "testDone", "log", "moduleStart", "moduleDone", "done"];
-       for (var i = 0; i < logs.length; i++) {
-               createCallback(logs[i]);
-       }
-}());
-
 module("logs1");
 
 test("test1", 15, function() {
-       equal(begin, 1);
-       equal(moduleStart, 1);
-       equal(testStart, 1);
-       equal(testDone, 0);
-       equal(moduleDone, 0);
-
-       deepEqual(logContext, {
+       equal( begin, 1, "QUnit.begin calls" );
+       equal( moduleStart, 1, "QUnit.moduleStart calls" );
+       equal( testStart, 1, "QUnit.testStart calls" );
+       equal( testDone, 0, "QUnit.testDone calls" );
+       equal( moduleDone, 0, "QUnit.moduleDone calls" );
+       deepEqual( logContext, {
                name: "test1",
                module: "logs1",
                result: true,
-               message: undefined,
+               message: "QUnit.moduleDone calls",
                actual: 0,
-               expected: 0
-       });
-       equal("foo", "foo", "msg");
+               expected: 0,
+       }, "log context after equal(actual, expected, message)" );
+
+       equal( "foo", "foo" );
        deepEqual(logContext, {
                name: "test1",
                module: "logs1",
                result: true,
-               message: "msg",
+               message: undefined,
                actual: "foo",
                expected: "foo"
-       });
-       strictEqual(testDoneContext, undefined);
-       deepEqual(testContext, {
-               module: "logs1",
-               name: "test1"
-       });
-       strictEqual(moduleDoneContext, undefined);
-       deepEqual(moduleContext, {
-               name: "logs1"
-       });
-       ok(true, "msg");
-       deepEqual(logContext, {
+       }, "log context after equal(actual, expected)" );
+
+       ok( true, "ok(true, message)" );
+       deepEqual( logContext, {
                module: "logs1",
                name: "test1",
                result: true,
-               message: "msg"
-       });
+               message: "ok(true, message)"
+       }, "log context after ok(true, message)" );
+
+       strictEqual( testDoneContext, undefined, "testDone context" );
+       deepEqual( testContext, {
+               module: "logs1",
+               name: "test1"
+       }, "test context" );
+       strictEqual( moduleDoneContext, undefined, "moduleDone context" );
+       deepEqual( moduleContext, {
+               name: "logs1"
+       }, "module context" );
 
-       equal(log, 14);
+       equal( log, 14, "QUnit.log calls" );
 });
-test("test2", 10, function() {
-       equal(begin, 1);
-       equal(moduleStart, 1);
-       equal(testStart, 2);
-       equal(testDone, 1);
-       equal(moduleDone, 0);
-
-       deepEqual(testDoneContext, {
+test("test2", 11, function() {
+       equal( begin, 1, "QUnit.begin calls" );
+       equal( moduleStart, 1, "QUnit.moduleStart calls" );
+       equal( testStart, 2, "QUnit.testStart calls" );
+       equal( testDone, 1, "QUnit.testDone calls" );
+       equal( moduleDone, 0, "QUnit.moduleDone calls" );
+
+       ok( typeof testDoneContext.duration === "number" , "testDone context: duration" );
+       delete testDoneContext.duration;
+       deepEqual( testDoneContext, {
                module: "logs1",
                name: "test1",
                failed: 0,
                passed: 15,
                total: 15
-       });
-       deepEqual(testContext, {
+       }, "testDone context" );
+       deepEqual( testContext, {
                module: "logs1",
                name: "test2"
-       });
-       strictEqual(moduleDoneContext, undefined);
-       deepEqual(moduleContext, {
+       }, "test context" );
+       strictEqual( moduleDoneContext, undefined, "moduleDone context" );
+       deepEqual( moduleContext, {
                name: "logs1"
-       });
+       }, "module context" );
 
-       equal(log, 24);
+       equal( log, 25, "QUnit.log calls" );
 });
 
 module("logs2");
 
-test("test1", 9, function() {
-       equal(begin, 1);
-       equal(moduleStart, 2);
-       equal(testStart, 3);
-       equal(testDone, 2);
-       equal(moduleDone, 1);
+test( "test1", 9, function() {
+       equal( begin, 1, "QUnit.begin calls" );
+       equal( moduleStart, 2, "QUnit.moduleStart calls" );
+       equal( testStart, 3, "QUnit.testStart calls" );
+       equal( testDone, 2, "QUnit.testDone calls" );
+       equal( moduleDone, 1, "QUnit.moduleDone calls" );
 
-       deepEqual(testContext, {
+       deepEqual( testContext, {
                module: "logs2",
                name: "test1"
-       });
-       deepEqual(moduleDoneContext, {
+       }, "test context" );
+       deepEqual( moduleDoneContext, {
                name: "logs1",
                failed: 0,
-               passed: 25,
-               total: 25
-       });
-       deepEqual(moduleContext, {
+               passed: 26,
+               total: 26
+       }, "moduleDone context" );
+       deepEqual( moduleContext, {
                name: "logs2"
-       });
+       }, "module context" );
 
-       equal(log, 33);
+       equal( log, 34, "QUnit.log calls" );
 });
-test("test2", 8, function() {
-       equal(begin, 1);
-       equal(moduleStart, 2);
-       equal(testStart, 4);
-       equal(testDone, 3);
-       equal(moduleDone, 1);
-
-       deepEqual(testContext, {
+test( "test2", 8, function() {
+       equal( begin, 1, "QUnit.begin calls" );
+       equal( moduleStart, 2, "QUnit.moduleStart calls" );
+       equal( testStart, 4, "QUnit.testStart calls" );
+       equal( testDone, 3, "QUnit.testDone calls" );
+       equal( moduleDone, 1, "QUnit.moduleDone calls" );
+
+       deepEqual( testContext, {
                module: "logs2",
                name: "test2"
-       });
-       deepEqual(moduleContext, {
+       }, "test context" );
+       deepEqual( moduleContext, {
                name: "logs2"
-       });
+       }, "module context" );
 
-       equal(log, 41);
+       equal( log, 42, "QUnit.log calls" );
 });
 
 var testAutorun = true;
index 8058e6b..e896f9d 100644 (file)
@@ -1,3 +1,43 @@
+function getPreviousTests( rTestName, rModuleName ) {
+       var testSpan, moduleSpan,
+               matches = [],
+               i = 0,
+               rModule = /(^| )module-name( |$)/,
+               testNames = typeof document.getElementsByClassName !== "undefined" ?
+                       document.getElementsByClassName("test-name") :
+                       (function( spans ) {
+                               var span,
+                                       tests = [],
+                                       i = 0,
+                                       rTest = /(^| )test-name( |$)/;
+                               for ( ; (span = spans[i]); i++ ) {
+                                       if ( rTest.test( span.className ) ) {
+                                               tests.push( span );
+                                       }
+                               }
+                               return tests;
+                       })( document.getElementsByTagName("span") );
+
+       for ( ; (testSpan = testNames[i]); i++ ) {
+               moduleSpan = testSpan;
+               while ( (moduleSpan = moduleSpan.previousSibling) ) {
+                       if ( rModule.test( moduleSpan.className ) ) {
+                               break;
+                       }
+               }
+               if ( (!rTestName || rTestName.test( testSpan.innerHTML )) &&
+                       (!rModuleName || moduleSpan && rModuleName.test( moduleSpan.innerHTML )) ) {
+
+                       while ( (testSpan = testSpan.parentNode) ) {
+                               if ( testSpan.nodeName.toLowerCase() === "li" ) {
+                                       matches.push( testSpan );
+                               }
+                       }
+               }
+       }
+       return matches;
+}
+
 test("module without setup/teardown (default)", function() {
        expect(1);
        ok(true);
@@ -490,6 +530,7 @@ test("setup", function() {
        expect(0);
        document.getElementById("qunit-fixture").innerHTML = "foobar";
 });
+
 test("basics", function() {
        equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
 });
@@ -503,6 +544,41 @@ test("running test name displayed", function() {
        ok( /fixture/.test(displaying.innerHTML), "Expect module name to be found in displayed text" );
 });
 
+(function() {
+       var delayNextSetup,
+               sleep = function( n ) {
+                       stop();
+                       setTimeout( function() { start(); }, n );
+               };
+
+       module("timing", {
+               setup: function() {
+                       if ( delayNextSetup ) {
+                               delayNextSetup = false;
+                               sleep( 250 );
+                       }
+               }
+       });
+
+       test("setup", 0, function() {
+               delayNextSetup = true;
+       });
+
+       test("basics", 2, function() {
+               var previous = getPreviousTests(/^setup$/, /^timing$/)[0],
+                       runtime = previous.lastChild.previousSibling;
+               ok( /(^| )runtime( |$)/.test( runtime.className ), "Runtime element exists" );
+               ok( /^\d+ ms$/.test( runtime.innerHTML ), "Runtime reported in ms" );
+       });
+
+       test("values", 2, function() {
+               var basics = getPreviousTests(/^setup$/, /^timing$/)[0],
+                       slow = getPreviousTests(/^basics$/, /^timing$/)[0];
+               ok( parseInt( basics.lastChild.previousSibling.innerHTML, 10 ) < 50, "Fast runtime for trivial test" );
+               ok( parseInt( slow.lastChild.previousSibling.innerHTML, 10 ) > 250, "Runtime includes setup" );
+       });
+})();
+
 }
 
 module("custom assertions");
@@ -653,22 +729,10 @@ function testAfterDone() {
                // work we use this test to check the assertion count.
                module("check previous test's assertion counts");
                test('count previous two test\'s assertions', function () {
-                       var i, countNodes,
-                               spans = document.getElementsByTagName('span'),
-                               tests = [];
-
-                       // Find these two tests
-                       for (i = 0; i < spans.length; i++) {
-                               if (spans[i].innerHTML.indexOf(testName) !== -1) {
-                                       tests.push(spans[i]);
-                               }
-                       }
+                       var tests = getPreviousTests(/^ensure has correct number of assertions/, /^Synchronous test after load of page$/);
 
-                       // Walk dom to counts.
-                       countNodes = tests[0].nextSibling.nextSibling.getElementsByTagName('b');
-                       equal(countNodes[1].innerHTML, "99");
-                       countNodes = tests[1].nextSibling.nextSibling.getElementsByTagName('b');
-                       equal(countNodes[1].innerHTML, "99");
+                       equal(tests[0].firstChild.lastChild.getElementsByTagName("b")[1].innerHTML, "99");
+                       equal(tests[1].firstChild.lastChild.getElementsByTagName("b")[1].innerHTML, "99");
                });
        }
        QUnit.config.done = [];

Hosting is provided AltSPAHow to use Git
Please direct any questions on jabber alex.wolf@jabber.ru

Valid HTML 4.0 Transitional Valid CSS!

Designer Alexander Wolf