Getting Started With QUnit Testing |
Written by Ian Elliot | |||||||||
Thursday, 09 February 2017 | |||||||||
Page 2 of 2
The AssertionsFrom here your task is to add assertions there are most likely to catch errors in the functions within the JavaScript file that you are testing. As well as the ok assertion that are a number of others that you need to know about:
There is also notOk, notEqual, notStrictEqual, notDeepEqual and notPropEqual which are sometimes easier to read than negating an assertion. You do have to be careful how you use these assertions otherwise you could well trigger failures that aren't justified. If it really is ok for a function to return anything that can be treated as a value then use equal if not use strictEqual. That is
and
You need to use the assertion that fits in with the way that the function you are testing is going to be used in practice. The only assertion that might be a tiny bit complicated is deepEqual. This is used to test that two objects, including arrays and even strings, have the same properties with identical values. The meaning of this is clear where the values are primitive types such as numeric values but what if the value is itself an object complete with properties? In this case the deepEqual assertion is applied to the object to make sure it is deepEqual to the target value. Notice that this is not equality of reference - i.e. the two objects can be distinct rather just the same object referenced by two variables. For example:
both assertions pass but the first is an equality of reference, i.e. both A and B reference the same object and the second is equality of value because the object that A references is a different object to the object literal in the assertion. The Global NamespaceThere is one very important testing feature that is quick to describe, easy to use and will save you hours. If you are writing quality JavaScript code then no function should add to the global namespace unless it is doing something very strange. However all you have to do is to forget to write a var in front of the first use of a variable and the global namespace is polluted. To detect that this has happened all you have to do is to select the Check for Globals box in the test page and the tests will be run again with an extra assertion automatically applied to every function that the global namespace should be the same before and after the function has been used. For example if you change the max function to:
and run the tests again with Check for Globals on you will see the message:
Testing HTMLThere has been a missing set of elements in all our tests so far - the HTML that the JavaScript often interacts with. How can we test a function that modifies some HTML by interacting with the DOM? The JavaScript we are testing probably works with some production HTML page and we don't want to pull this into the testing page. There is also the problem of side effects. If you run a test on a function and it modifies the DOM how might this effect other functions tested later? The issue of side effects and how to handle them is a big problem in general testing but for JavaScript it is the DOM - a global resource that is the big headache. Fortunately QUnit gives us an easy solution. You can use a Div with the id qunit-fixture to contain any HTML you want to be available to test your functions. When you run the a test it can modify anything in the fixture div and when it has finished QUnit will restore the DOM to its state before the function ran. That is the fixture div is your HTML playground where you can do anything you want safe in the knowledge that it will not effect anything that follows. Of course if you do want to keep side effects simply create the testing HTML in the web page and not in the fixture div. Notice that the DOM is restored to its original state after the test is complete not after each assertion. For example, suppose we have the function:
then to test it we add to the testing page:
Now we can add two tests:
The first test runs the function which modifies the DOM and the assertion checks that the DOM has indeed been modified. The first test then ends and the DOM is restored to its original state. When the second test starts the assertion it contains fails because the DOM element doesn't contain "Hello QUnit" because the changes have been reset. By grouping tests together you can construct assertions where changes propagate to later assertions and you can use separate tests to reset the DOM. Asynchronous TestsSooner or later you will encounter the need to test a function that is asynchronous. In this case you need QUnit to wait for it to complete any assertions which have become asynchronous. For example suppose myAsync accepts a callback that is run when it is complete. You might write something like:
This is perfectly logical in that you want to test the value returned sooner or later by myAsync to the callback but as it is things will be a little strange. The reason is that QUnit will continue on its way running assertions and tests before the callback with the equal assertion is called. To keep things in the right order we can stop QUnit and restart it after the assertions have been run in the callback. To do this we need to use the async function which returns a done function which can be used to signal that the asynchronous call is complete. That is:
The call to async halts the running of tests while myAsync function is working. When it finally called the callback an assertion is computed and the test engine restarted by the call to done. Notice that the call to done is within the callback function. If the test involves more than one asynchronous call you can specify the number as a parameter in the async call. That is:
specifies that two async operations will occur before the test is complete. In this case you need to call done twice to restart testing. Where nextThere are lots of other features of QUnit that make testing more powerful and better organized, but you now have the basics. You now know that you don't change the production code to test it. You simply create a test page which runs tests, each test consisting of a set of assertions. You also now know how to provide an HTML playground for the functions to exercise themselves in. From here you need to look up the use of modules to group tests together and you need to find out how to add custom assertions, but these things can wait until you need to make use of them. Testing and development should go hand-in-hand and now you have no excuse for not adding a testing page to your project. Related ArticlesQUnit Javascript Unit Tester Released
Available as a Book:
buy from Amazon
Also Available:buy from Amazon
To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.
Comments
or email your comment to: comments@i-programmer.info
|
|||||||||
Last Updated ( Sunday, 19 February 2017 ) |