Join the DZone community and get the full member experience.Join For Free
Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.
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:
- Write your test first, and see it fail. (Red)
- Write your unit of code and see the test pass. (Green)
- Make your code better, using the tests to keep you safe. (Refactor)
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.
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 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.
Highly configurable- Installation and configurations are simple and can be done quickly. Also, Karma integrates with popular continuous integration packages (Jenkins, 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:
|Test Coverage||Reports how much of your code has been tested|
|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 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.
|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|
|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.
Opinions expressed by DZone contributors are their own.