JavaScript Unit Testing with TDD, Jasmine and Karma

In this article, we’ll introduce you to a tool combination which will make JavaScript unit testing so much easier. Jasmine and Karma combined will save you hours of testing.

First, let’s understand what exactly are TDD, Jasmine and Karma.

Test driven development (TDD) is one of the main, agile development techniques. The genius of TDD lies in writing your test’s code first, so it can guide your further implementations. This method provides you with an increased quality of code, improved bug detection and overall faster development. The bigger and more important the system you’re building, the more helpful these techniques will be:

  1. Write your test first, and see it fail. (Red)
  2. Write your unit of code and see the test pass. (Green)
  3. Make your code better, using the tests to keep you safe. (Refactor)

Jasmine is a Behavior Driven Development (BDD) testing framework for JavaScript. It does not rely on any browsers, DOM, or JavaScript frameworks. Therefore, it’s suited for websites, Node.js projects, or anywhere JavaScript can run on. It also has runners in Python and Ruby, which  can assist you incredibly if you want to run your client-side tests alongside your server-side ones.

Karma is essentially a simple open source tool that allows you to execute JavaScript code in multiple browsers. It spawns a web server that executes source code against test code for each of the browsers connected. The results of each test against each browser are examined and displayed via the command line to the developer in order to reveal which browsers and tests passed or failed.

Making your life easier down the line, TDD was meant to eliminate your excuses regarding skipping the testing of a program. Which in most times, doesn’t affect anything, and you successfully move your code to production without any problems. Although sometimes, after you’ve moved to production, everything goes wrong. You’re stuck fixing too much, with more problems appearing every minute- a situation in which you do not want to find yourself.

When a program is developed using TDD, it allows us to make changes and test quickly and efficiently. All we need to do is run the automated tests. If the program passes all automated tests, then we’re good to go—if not, then it just means we broke something along the way with the changes we’ve made. By knowing which exact parts of the test failed, it also allows us to easily pinpoint which changes made it happen, so it makes fixing the bugs easier.

Looking at past experiences, TDD has been difficult to be executed with JavaScript based solutions. Design patterns that facilitated the intermingling of functions that manipulate UI interface objects with underlying functionality, resulted in large and complex HTML pages with huge blocks of JavaScript code. Any Changes to the UI would make significant changes, which is problematic, because it requires constant unit test updates, which most development teams either won’t initiate or quickly abandon their attempts to work around the TDD method.

That is where Jasmine and Karma come in. Jasmine is a great framework for providing unit testing and end-to-end, acceptance testing. Coupled with Karma, Jasmine can monitor file changes to source files and execute tests on every file change to make sure that all tests are always passing, a perfect match for TDD/BDD environment. The main point is that if you have something quite complex and you make changes that might end up affecting several other functions, Jasmine and Karma are basically a way of verifying everything still works after a code update or restructuring.

Karma is as a direct product of the AngularJS team’s struggles to test their own framework features with existing tools. Therefore, you can understand why both Karma and Jasmine are perfect for working with AngularJS.

Now let’s dive deeper with an overview of Karma and Jasmine’s main features and utilities:

Karma

Highly configurable- Installation and configurations are simple and can be done quickly. Also, Karma integrates with popular continuous integration packages (Jenkins CI server, Travis, and Semaphore) and has an excellent plugin support.

Cross device and cross platform- Have those tests executed not only in the browsers of your choice, but also on the platform of your choice (desktop, phone, tablet and even a PS3 like the YouTube team.)

Additional useful Karma Plugins– Karma offers a vast list of helpful plugins created by other users constantly, and the option to customize your own. But some, are extra helpful to supercharge your tests, especially with AngularJS:

Plugin Description
Test Coverage Reports how much of your code has been tested
JSHint Will detect errors and violations in JavaScript
NG-HTML2JS For unit testing directives that use the templateUrl setting or routes, it allows converting HTML files to JS files. Otherwise, running the tests might end up in this error: “Unexpected request: GET partials/directive.html No more request expected”

Jasmine

Jasmine is full of handy matchers:

  • Jasmine jQuery– Provides matchers for jQuery objects, and an easy way to build HTML fixtures to test with.
  • Underscore Matchers for Jasmine– Provides matchers based on the methods in Underscore.js. Particularly useful for Backbone projects.
  • AngularJS Matchers- Provides matchers for working with the AngularJS framework.
  • You can write your own customized matchers.
Matcher Description
toBe Compares actual and expected with ===
toEqual Compares simple object literals that === cannot
toMatch Compares actual value against a regular expression
toBeDefined Checks to see if the actual value is defined
toBeUndefined Checks to see if the actual value is undefined
toBeNull Checks to see if the actual value is null
toBeTruthy Checks to see if the actual value coerces to true
toBeFalsy Checks to see if the actual value coerces to false
toContain Checks to see if an array contains the expected value
toBeLessThan Self-explanatory
toBeGreaterThan Self-explanatory
toBeCloseTo For precision math comparisons on floating point numbers
toThrow Checks to see if an error is thrown
toHaveBeenCalled Checks to see if the spy was called
toHaveBeenCalledWith Checks to see if the spy was called with the expected parameters
  • jasmine.any- A helper that lets you match against a constructor or “class”.
  • Spies- Are incredibly powerful, they can be used to fake objects and functions in more ways than we have time to cover.
  • Async testing support- Jasmine offers a handy function called “callFake()”. In your beforeEach, you can setup the functions to spyOn, but you can also add a callFake- you are able to inject a call into the end of the function, and tell Jasmine the test is done, by calling done.
  • Jasmine’s introduction- Is mostly good; although, it isn’t the simplest if you’re new to Jasmine. The greatest thing about it is the fully descriptive examples.
  • Writing specs in CoffeeScript makes them easier to read. Specs can run as part of CI test suite, just like your back end code. You don’t have to run a browser to see what’s going on- you can automatically kick start your specs every time you save and the ability to get an instant feedback makes it much easier to keep moving you forward in your process.

To summarize, it is possible to upgrade your code testing experience. The TDD method with Jasmine and Karma combined is what you are looking for. Both complement each other and guarantee a greater quality of code, quicker progress and control over the effect of changes made along the way.

 


Join the discussion, we’ll  be happy to know about your JavaScript unit testing experience  😎

Do you have experience with Jasmine and Karma in a TDD environment?

What are your suggestions for a better code testing experience?