This is the 18th Testing Tuesday episode. Every week we will share our insights and opinions on the software testing space. Drop by every Tuesday to learn more! Last week we spied on JavaScript methods with Jasmine.

Testing asynchronous JavaScript operations

In the last two Testing Tuesday episodes we already got familiar with Jasmine. If you haven’t already, watching Testing Tuesday #16 will make it easier to follow along this episode.

JavaScript is the perfect language for asynchronous operations. But although they make our apps fast, elegant and responsive, they are also a challenge to test.

Transcript

Testing asynchronous JavaScript with Jasmine

Intro

Ahoy and welcome! My name is Clemens Helm and this is Codeship’s Testing Tuesday number 18! At the moment I do a lot of front end work at the Codeship and I’m falling in love with JavaScript all over again. That’s why this episode is once more about testing Javascript with Jasmine. Last week we spied on methods to find out if and how they got called. This week we tackle one of the trickiest parts of JavaScript applications: Testing asynchronous operations.

Screencast

In the last two Testing Tuesday episodes we already got familiar with Jasmine. If you haven’t already, watching Testing Tuesday #16 will make it easier to follow along this episode. I’ll link to it in the further info section.

JavaScript is the perfect language for asynchronous operations. But although they make our apps fast, elegant and responsive, they are also a challenge to test. Jasmine lets us test asynchronous applications by waiting for certain events to occur until there’s a timeout.

This week we’re developing an application for racing robots. We’ve got a Robot that stands at 0 meters.

function Robot() {
this.meters = 0;
this.motion = "stopped";
}

We can make it run a few meters though. The robot moves at variable speed. It will make for sure 1 meter per second, but it can also be much faster. We represent this variation with Math.random(). When we call the runMeters method, the robot will start running immediately. After the time it needs to run it will stop at the specified position.

The problem is that it takes some time for the robot to reach its destination, but we check the expectations right after it started running. But how can we check our expectations once the robot stopped again? Jasmine provides a waitsFor method to wait for events to happen:

So we’ve got two block here: waitsFor and runs. These blocks will be executed subsequently. waitsFor expects a function with a condition, an error message and a timeout. It will poll until the condition is met or the timeout expires. If the timeout expires, the spec fails with the error message given. We can try this by passing a very little timeout:

When the waitsFor condition is met, the spec procedes with the next runs block. In our case, this will check if the robot has run 5 meters. Let’s change the timeout to 5 seconds again and run the specs

This doesn’t work, because the spec finishes before the callback function is invoked. But even if it worked, it would be much slower: Maybe it took our robot just a few milliseconds to run 5 meters, but we would still need to wait 5 seconds. waitsFor polls for the condition all the time and procedes immediately as soon as it’s true. When your spec suite grows, this will make a tremendous difference to your spec execution time.

This will mock the JavaScript time, so it’s a great way to make setTimeout functions start sooner. In our case this works very well: The clock lets 5 seconds pass and our robot has reached our destination immediately. However, since the clock mock overrides the global JavaScript time, this can lead to unexpected behavior.

This approach also only works, when you are testing a self-contained application. As soon as you have to wait for external dependencies like a database query or an AJAX call, mocking the time won’t work anymore, because time still runs normally outside of your JavaScript runtime.

Outro

So Jasmine is a great tool for testing asynchronous operations. Next week we’ll take a look at testing your Node.js applications with Jasmine. Stay tuned and – most of all – always stay shipping!