Justifying and Realizing a Strong ROI on Test Automation Sign up now

QUnit Tutorial: Start Unit Testing and Measuring Code Coverage

There are many libraries available to write unit tests for your JavaScript code. One popular option is QUnit. Let's look…

By Testim,

There are many libraries available to write unit tests for your JavaScript code. One popular option is QUnit. Let’s look at how you can get started with QUnit. But let’s not stop there. Measuring code coverage of your tests is a useful metric to gain insights and improve your test suite.

What Is QUnit?

If you’re already familiar with QUnit, you can skip to the next section.

QUnit is a JavaScript library to test your JavaScript code. You can write your tests using certain functions provided by QUnit and then have QUnit run them. QUnit can run your tests in the browser or in a plain Node.js process.

Which way of running your tests depends mainly on where your code will run. If your JavaScript code will run in the browser (i.e. you’re using the DOM), you might want to run your unit tests in the browser as well. You can run QUnit with Node.js if you’re writing a Node.js application.

If you’re testing logic that will run in the browser but doesn’t interact with the DOM, I recommend running your tests in a Node.js process. It will also be easier to integrate with a CI/CD pipeline.

The Code We’ll Test

Before we can write a unit test, we need some code that we want to test. Let’s assume we’re loading a page and providing it with some data. This data contains names that we want to display. We want to display it in a readable way, so we’ll prepend the last element with “and”.

This is our HTML file:

And this is our JavaScript code in the index.js file:

This gives us the following result:

qunit tutorial

Now let’s write a test.

Our First QUnit Test

We’ll start by running our QUnit tests in the browser. To do this, we need a webpage where QUnit is loaded and where it can run:

Basically, we’re

  • loading the QUnit script and CSS files
  • providing two divs for QUnit
  • a div for our script to manipulate
  • loading our index.js script
  • and a script containing our tests

Now, for our tests.js file. We’re going to call the QUnit.test function and provide it a test name and a callback. It’s in the callback that we’ll verify the results of our index.js script:

When we load our tests.html page now, we see the results:

qunit tutorial

But this example is too simple. The data is hard-coded and we want to run it for different sets of data. We need a way of providing our code with other data.

Improving the Code

Let’s extract our code into a function first:

We’ll move the “production” code to retrieve the data to our index.html page:

This way it won’t interfere with our tests.

Now, we can write multiple tests:

One test fails however:

qunit tutorial

We can easily fix this by changing our code:

Our tests now pass:

qunit tutorial

The nice thing is that I can add many tests to this suite, without having to load my application over and over again. This really improves my development speed.

There is another improvement we can make. We had to add a h1 tag to our HTML page. But what if we have many tests that require different kinds of HTML tags? Our test page would quickly become a mess. It also means our tests could start influencing each other, i.e. a test that runs fine by itself fails when run as part of the larger suite.

Isolating Our Tests

It’s a best practice to have each unit test run in isolation. This is true for unit tests in every language or framework. QUnit has us covered with the qunit-fixture div. We can use this div to add the elements that we need. QUnit will clean up this div after each test has run.

This is what one test could look like:

We’re adding a div tag to our qunit-fixture div and QUnit will reset the state of the qunit-fixture after every test. If we do the same thing for our other tests, we can see that our tests still pass:

qunit tutorial

Notice how we have some duplicate code to add the pageTitle element to our qunit-fixture element? When your test suite really starts to grow, you’ll want to organize your tests into modules and reuse code that you keep repeating.

Organizing QUnit Tests With Modules

Creating a module in QUnit is easy. Just call QUnit.module and any test declared after that line will be added to the module. A better approach is to add a callback function to QUnit.module so that you can nest modules.

You can also use the beforeEach and afterEach functions to run code before (or after) each test. Let’s change our code to this:

Our results page now include the module name:

qunit tutorial

Once you have a lot of tests, you can nest modules and really start to organize your tests. I’ve stretched our example a bit to the point of being unrealistic, but this should give you an idea of what’s possible:

qunit tutorial

Once you have your tests organised in modules, you can use the filter in the top right to see only the tests you’re interested in:

qunit tutorial

Automating the Test Run

Instead of having to open the webpage in a browser each time, let’s create a script that can run the tests for us. Karma is a test runner that will spin up a browser for us. We can integrate it with QUnit and run our tests in a headless Chrome instance.

Let’s install the necessary dependencies first. Make sure you have npm installed and at the root of your project, run:

Then initialize a Karma config file:

You’ll get a series of questions to which most answers will be straightforward. This is what I answered:

Karma will create the configuration file, but we still need to make one change. In the configuration file, change the singleRun value to true. You can now run your tests:

Our tests have now run in a headless version of Chrome:

Code Coverage

Our code now looks like this:

The tests enable us to easily add new features to the function without having to start the application each time to verify the results manually. But there is a small piece of code there that isn’t covered by tests:

We can easily see this now, but when you have a large body of tests, this isn’t always clear. This is where code coverage is useful. Code coverage will show you data on how many and which pieces of your code are covered by tests.

Let’s install code coverage for Karma:

Now when we run our tests (with the karma start command), a new folder coverage will appear, containing the results. Open the index.html page and you’ll see an overview:

You can click on the index.js link and you’ll see which parts aren’t covered yet:

We can now add a test to improve our code coverage.

Track Your Progress Going Forward

We’ve built a good basis to use QUnit for our tests and see where we need to add tests. If you want, you can check out the repository on GitHub.

Don’t focus on achieving 100% test coverage. That’s not necessary. But use the code coverage results to see where you’re missing tests that you feel should be present.

Over time you’ll notice the quality of your production code improves, and you feel safer changing code. Have fun testing!

This post was written by Peter Morlion. Peter is a passionate programmer that helps people and companies improve the quality of their code, especially in legacy codebases. He firmly believes that industry best practices are invaluable when working towards this goal, and his specialties include TDD, DI, and SOLID principles.

Testim's latest articles, right in your inbox.

From our latest feature releases, to the way it impacts the businesses of our clients, follow the evolution of our product

Blog Subscribe