Manual:JavaScript unit testing/QUnit guidelines

From MediaWiki.org
Jump to: navigation, search

QUnit comparisons[edit | edit source]

If at all possible use comparing functions such as equal(), strictEqual() etc. instead of ok(). In most unit testing because it is more useful to have both the expected value and resulting value available to the debugger. When using ok() it forces one to do the contrary and make comparison inline (since ok() only takes one value). In case of a failure, ok() only reports "Passed" or "Failed", whereas equal() (having both values), can output useful debug information. This is especially important when working with test reports generated externally (eg. from Jenkins) in which case the test report is all you have.

// Not very useful, the comparison is done inline and ok()
// can only know about the result of the comparison
var x = 'foo';
assert.ok( x === 'bar' ); // Failed.
assert.ok( x === 'foo' ); // Passed.
// Useful! The unit test is give both values so it can also mention
// both in the output:
var x = 'foo';
assert.equal( x, 'bar' ); // Failed. Expected: "bar". Result: "foo"
assert.equal( x, 'foo' ); // Passed. Expected: "foo".

In cases where it exact value is too variable or doesn't matter, all it matters is that it is not falsy, then ok() use is fine:

assert.ok( $.fn.myPlugin, 'Plugin is loaded succesfully' );

But even then it can sometimes be more useful to do a type check. Suppose a variable is declared early and populated later, then you'll want to know more and a type check would report the type of value it contains when it's not what you expected. Below example is using $.type() since JavaScript's built-in typeof is flawed[1][2].

assert.equal( $.type( mw.Foo.quuxes ), 'array', 'Quux is initialized as an array' );
// Failed. Expected: "array". Result: "string"
// or:
// Passed. Expected: "array".
 
// Compared to:
assert.ok( mw.Foo.quuxes, 'Quux is initialized as an arra' );
assert.ok( $.type( mw.Foo.quuxes ) ===  'array', 'Quux is initialized as an arra' );
// Both only report "Failed." or "Passed." the actual type is not reported..

In the above example the report includes not only the failure ("type is not array"), but also what it actual value was ("result type: string"). This is possible because QUnit is given the type-value instead of the result of comparing the type.


When dealing with objects (such as arrays, object literals and other objects) one can't use equal to compare the key/value pairs. In such case one has to use deepEqual which will loop over the object and compare the key/values themselves:

var a = ['foo', 'bar'];
assert.equal(a, ['foo', 'bar'], 'Variable"a" should be an array with "foo" and "bar".');
assert.strictEqual(a, ['foo', 'bar'], 'Variable"a" should be an array with "foo" and "bar".');
// Both of the above will report "Failed". Because objects are compared by reference
// That's useful for some purposes but not this case. Use deepEqual:
 
assert.deepEqual(a, ['foo', 'bar'], 'Variable"a" should be an array with "foo" and "bar".');
// Passed. Expected: ['foo', 'bar']

Test elements[edit | edit source]

The <div id="qunit-fixture"></div> element can be used to add extra elements to manipulate, and will be automatically reset after each test (see QUnit.reset()). The element is styled with position:absolute; top:-10000px; left:-10000; with these, it won't be obstructing the result, without affecting code the relies on the affected elements to be visible (instead of display:none).

See also[edit | edit source]

References[edit | edit source]

  1. JavaScript Garden - The typeof Operator
  2. MDN - typeof