Speeding Up CI with Karma’s Real‑Browser Parallel Testing
Learn how to configure Karma to run JavaScript unit tests in multiple real browsers at once, using the parallel plugin to cut CI feedback time while keeping test fidelity.
26 May 2026, 06:58 UTC

Problem: Slow CI feedback from sequential browser runs
When a test suite grows, waiting for Karma to finish a single‑browser run can add minutes to every CI build. The delay slows down developer feedback and makes it harder to catch regressions early.
Takeaway: By configuring Karma to launch several real browsers in parallel and sharding test files across those processes, you can cut total runtime while still testing against genuine DOM environments.
How Karma executes tests in real browsers
Karma does not simulate the browser; it uses launcher plugins such as karma-chrome-launcher and karma-firefox-launcher to spawn actual Chrome or Firefox instances. Each launcher opens a browser, loads the test harness, and communicates results back to the Karma server through a socket. This gives you real‑world layout, event handling, and JavaScript engine behavior—something a jsdom‑based runner cannot guarantee.
Adding parallel execution with the karma‑parallel plugin
The karma-parallel plugin splits your test files into shards and distributes those shards across the available browser instances. Each shard runs in its own browser process, so the total wall‑clock time approximates the longest shard rather than the sum of all tests.
Example karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: [
'src/**/*.js',
'test/**/*.spec.js'
],
browsers: ['ChromeHeadless', 'FirefoxHeadless'],
plugins: [
'karma-*',
'karma-parallel'
],
concurrency: require('os').cpus().length,
reporters: ['progress', 'coverage'],
coverageReporter: {
dir: 'coverage/',
subdir: '.',
reporters: [{ type: 'lcov', subdir: '.' }]
}
});
};
Place this file in the root of your project (next to package.json). The concurrency setting tells Karma how many browser instances to start simultaneously; using the number of CPU cores is a common starting point. The browsers array lists the launchers you have installed—make sure the corresponding karma-*-launcher packages are present in node_modules.
Running the suite
From the project root, execute:
npx karma start --browsers ChromeHeadless,FirefoxHeadless --parallel
You need read/write access to the project directory and the ability to spawn processes (standard CI agent permissions are sufficient). No special privileges are required.
During the run you should see log lines similar to:
ChromeHeadless: running 4 of 12 testsFirefoxHeadless: running 5 of 12 testsChromeHeadless: finished 4 tests in 0.32s
These messages indicate that the test files have been divided into shards and each browser is reporting its own progress.
Trade‑offs and limitations
The parallel approach assumes that tests are isolated. If your suite relies on global state, mutable singletons, or side‑effects that persist between files, shards can interfere with each other and produce flaky failures. Before enabling parallelism, run the suite a few times with the --single-run flag and look for inconsistent results.
Real browsers consume more memory and CPU than a headless jsdom environment. On a CI agent with limited resources, launching many instances at once can lead to out‑of‑memory kills or excessive swap usage. Monitor the agent’s memory consumption (e.g., via ps or container metrics) and adjust the concurrency value downward if needed.
Finally, the coverage aggregation works only when the coverage reporter is configured to merge reports from all shards. The coverageReporter block shown above writes a single lcov.info file that contains contributions from every browser; you can verify this by checking that the file size grows proportionally with the number of shards.
Actionable closing
- Install the launchers and parallel plugin:
npm install --save-dev karma-chrome-launcher karma-firefox-launcher karma-parallel. - Add or edit
karma.conf.jsusing the snippet above. - Run a trial build with the command shown and inspect the console for shard messages.
- After the run, open
coverage/lcov.infoand confirm that each source file appears with non‑zero coverage. - If you notice flaky failures, isolate the offending tests or reduce concurrency until the suite stabilizes.
- Once the configuration passes reliably on your CI agent, commit the changes and enjoy faster feedback loops.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.