Skip to content

Commit

Permalink
Add QUnit.pushFailure to log error conditions like exceptions. Accept…
Browse files Browse the repository at this point in the history
…s stacktrace as second argument, allowing extraction with catched exceptions (useful even in Safari). Remove old fail() function that would just log to console, not useful anymore as regular test output is much more useful by now. Move up QUnit.reset() call to just make that another failed assertion. Used to not make a test fail. Fixes #210
  • Loading branch information
jzaefferer committed Mar 7, 2012
1 parent cd077bb commit af27eae
Showing 1 changed file with 52 additions and 40 deletions.
92 changes: 52 additions & 40 deletions qunit/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Test.prototype = {
try {
this.testEnvironment.setup.call(this.testEnvironment);
} catch(e) {
QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
}
},
run: function() {
Expand All @@ -111,8 +111,7 @@ Test.prototype = {
try {
this.callback.call(this.testEnvironment);
} catch(e) {
fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + ": " + e.message, extractStacktrace( e, 1 ) );
// else next test will carry the responsibility
saveGlobal();

Expand All @@ -131,17 +130,23 @@ Test.prototype = {
try {
this.testEnvironment.teardown.call(this.testEnvironment);
} catch(e) {
QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
}
}
checkPollution();
},
finish: function() {
config.current = this;
if ( this.expected != null && this.expected != this.assertions.length ) {
QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
} else if ( this.expected == null && !this.assertions.length ) {
QUnit.ok( false, "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions." );
QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions." );
}

try {
QUnit.reset();
} catch(e) {
QUnit.pushFailure( "reset() failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
}

var good = 0, bad = 0,
Expand Down Expand Up @@ -223,12 +228,6 @@ Test.prototype = {
}
}

try {
QUnit.reset();
} catch(e) {
fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
}

runLoggingCallbacks( 'testDone', QUnit, {
name: this.testName,
module: this.module,
Expand Down Expand Up @@ -703,6 +702,23 @@ extend(QUnit, {
});
},

pushFailure: function(message, source) {
var details = {
result: false,
message: message
};
var output = escapeInnerText(message);
if (source) {
details.source = source;
output += '<table><tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';
}
runLoggingCallbacks( 'log', QUnit, details );
config.current.assertions.push({
result: false,
message: output
});
},

url: function( params ) {
params = extend( extend( {}, QUnit.urlParams ), params );
var querystring = "?",
Expand Down Expand Up @@ -924,26 +940,34 @@ function validTest( name ) {

// so far supports only Firefox, Chrome and Opera (buggy)
// could be extended in the future to use something like https://github.com/csnover/TraceKit
function sourceFromStacktrace(offset) {
function extractStacktrace( e, offset ) {
offset = offset || 3;
if (e.stacktrace) {
// Opera
return e.stacktrace.split("\n")[offset + 3];
} else if (e.stack) {
// Firefox, Chrome
var stack = e.stack.split("\n");
if (/^error$/i.test(stack[0])) {
stack.shift();
}
return stack[offset];
} else if (e.sourceURL) {
// Safari, PhantomJS
// hopefully one day Safari provides actual stacktraces
// exclude useless self-reference for generated Error objects
if ( /qunit.js$/.test( e.sourceURL ) ) {
return;
}
// for actual exceptions, this is useful
return e.sourceURL + ":" + e.line;
}
}
function sourceFromStacktrace(offset) {
try {
throw new Error();
} catch ( e ) {
if (e.stacktrace) {
// Opera
return e.stacktrace.split("\n")[offset + 3];
} else if (e.stack) {
// Firefox, Chrome
var stack = e.stack.split("\n");
if (/^error$/i.test(stack[0])) {
stack.shift();
}
return stack[offset];
} else if (e.sourceURL) {
// Safari, PhantomJS
// TODO sourceURL points at the 'throw new Error' line above, useless
//return e.sourceURL + ":" + e.line;
}
return extractStacktrace( e, offset );
}
}

Expand Down Expand Up @@ -1033,18 +1057,6 @@ function diff( a, b ) {
return result;
}

function fail(message, exception, callback) {
if ( typeof console !== "undefined" && console.error && console.warn ) {
console.error(message);
console.error(exception);
console.error(exception.stack);
console.warn(callback.toString());

} else if ( window.opera && opera.postError ) {
opera.postError(message, exception, callback.toString);
}
}

function extend(a, b) {
for ( var prop in b ) {
if ( b[prop] === undefined ) {
Expand Down

0 comments on commit af27eae

Please sign in to comment.