Manual:JavaScript unit testing/QUnit guidelines

Comparisons
Use comparing functions such as  and. Avoid passing expressions to.

Letting QUnit perform the comparison has several advantages:


 * Allows the test runner to display the difference between the expected and actual values. When using  it forces one to do inline expression, which loses this information. This is especially important when working with test reports generated externally (eg. from Jenkins or Karma) in which case the test output is all you have. (When running tests manually in a browser locally, one could set breakpoints etc.)
 * Passing an explicit expected value serves to self-document the expected result.
 * Using an explicit expected value avoids accidentally hiding regressions as result of type casting and non-strict comparisons.

In cases where the exact value is too variable or doesn't matter, you can still make an explicit comparison by checking its type (in case of a function), or its length (in case of an array or string). For example:

When dealing with objects (such as arrays, object literals, or other objects) one can't use  to compare the content. In such case one has to use, which will loop over the object and compare each key/value separately. For example:

Test elements
The QUnit runner automatically ensures the  element exists and is cleaned by QUnit before each test. Use this for any elements that need to be connected to the document. Avoid appending nodes elsewhere in the document as they may be left behind and affect other tests.

Asynchronous
Tests that assert the outcome of an asynchronous method (or a method that returns a promise), should have their return value returned from the  function. This allows QUnit to automatically track the promise without manually having to connect it with. This has the benefit of also automatically asserting that the Promise is resolved, and failing the test with the rejection error if the promise was rejected. No manual  statements needed.

If an asynchronous method is expected to be rejected rather than resolved, one can use, which behaves the same as returning a Promise to QUnit.test, except that it expects rejection rather than resolution.

Lastly, if a test is asynchronous but does not naturally provide a Promise, you can use  to manually track it. This is preferred over creating custom Promise or Deferred wrappers.

Data sourcing/seeding in Ajax requests
Because QUnit tests shouldn't depend by the data registered on the back-end (unless the test is not meant to verify a specific data-set available by default upon installation) the Ajax calls performed during tests requests should be handled using the following strategy:


 * if the result of an Ajax request only depends from the data provided by the client, or additional data retrieved on the server do not depend by a specific data-set, then a real Ajax request can be performed during the test, and the test can be verified either using  in conjunction with   or using a trigger
 * if the result of an Ajax request depends by a specific data-set registered on the back-end, then the result should be either overridden with data provided by the QUnit function, or the success callback should be directly executed with the provided data without performing the Ajax request.

The rationale is that if a QUnit test relies on specific data-set server-side, unless they are seeded on the back-end as part of the test, and unless such data is not installed by default, in a different environment the Javascript tests will fail as long as the same data-set won't be found. This is of course true for every Ajax request involved from the test, also indirectly, so check carefully all the workflow of your script to prevent errors!