How to set up and run fast Karma tests in front-end projects
The most front-end projects uses Karma as test runner for unit tests written in JavaScript. Karma executes tests in real and headless browsers. A well-established headless browser is PhantomJS. In this blog post, I will demonstrate an approach for rapid testing with Karma. The tests themselves are written with the well-known test framework Jasmine. We will also use the Webpack bundler and karma-webpack to bundle all tests together and prepare them for running in Karma.
Standard approach
Normally people run all tests at once. Let me show an example. As reference, I will use a Karma configuration from one of my POCs. This is a typically configuration to work smoothly with Webpack.
The file spec-bundle.js bundles all test files together. In TypeScript based projects, all test files end with .spec.ts. In JavaScript projects they would end with .spec.js. This is the best practice to give test files the names *.spec.js. A typically simple spec-bundle.js only has a couple of lines:
AngularJS 2 projects need a little bit more settings.
You can now write npm scripts in package.json like this one
and run all tests in one of these ways:
- npm test
- npm run test:headless
- npm run test:chrome
If you let running the tests in Chrome, a browser gets open and you see the button “Debug”. A click on this button opens a new browser tab where you are able to debug your tests in Chrome Dev Tools with breakpoints etc. F5 refreshes the page and starts the tests again.
Optimized approach
In a real web application you can have a lot of test files. The bundling and running of all test files might take a while. The Karma takes a while for the booting process as well. It is not satisfied for rapid software development if you always have to run hundreds and more tests in order to tests a small change in a single file. You would like to narrow testing for files you’re writing the tests for. Exactly one file or a specified collection of files should be tested. And that’s without rebooting the Karma. Hmm… How to do this?
This is the case where karma-webpack-grep can help you. It allows to limit files which are bundled by karma-webpack. First, install it.
After that we have to extend karma.conf.js file. Put a new karma-webpack-grep plugin to the array of all Webpack’s plugins. Everything else remains unchanged.
Note: testContext option is exactly the same as in the require.context(…) (see spec-bundle.js). But where config.grep is coming from? Karma parses command line args. That means, if you execute
the config.grep will be set to some/path. Let’s extend npm scripts
It’s a time to write some test with Jasmine. In my POC, I’ve written the following test:
This test file is located under src/app/model/emf/EMFRegistry. Now I’m able to run this test in one of two ways:
- npm run test:chrome:grep -- app/model/emf/EMFRegistry.spec.ts
- npm run test:headless:grep -- app/model/emf/EMFRegistry.spec.ts
We pass the path to the test file from src folder. Test result for PhantomJS looks like as follows
The Karma runner continues to run and watches the file changes. Test results appear very fast on every file change. It is also possible to watch and execute test files in a certain folder. For that, you can simple pass this folder to the npm script. For instance:
- npm run test:chrome:grep -- app/model/emf
All test under src/app/model/emf will be now watched and executed. Just concentrate on writing code.
Happy testing!