Stabilizing Karma CI Runs with Custom Launchers and Concurrency Tweaks
Stabilize Karma CI runs by tailoring custom browser launchers and limiting concurrency. Learn how to set up headless Chrome with sandbox flags, cap parallel instances, and verify the setup for reproducible, resource‑friendly test execution.
08 Aug 2025, 21:05 UTC

Problem: flaky, slow test runs in CI
Running JavaScript unit tests on a continuous‑integration server often feels like a guessing game. Tests that pass locally explode into failures when the CI machine has fewer CPU cores, less RAM, or a different browser version. Two common culprits are the way browsers are launched and how many of them run at once.
Thesis: tune Karma’s launchers and concurrency to match your CI envelope
By defining per‑environment launchers that pass the right flags to headless browsers and by capping the number of simultaneous instances, you can make Karma produce reproducible, fast, and resource‑friendly runs without touching test code.
1. Custom Browser Launchers
Karma lets you declare customLaunchers that inherit from built‑in ones. This is handy when the CI environment needs flags like --no-sandbox or --disable-dev-shm-usage to avoid silent failures.
module.exports = {
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox', '--disable-dev-shm-usage']
}
}
};
Run karma start --list-browsers to verify the launcher name shows up. If you upgrade to a newer Karma or launcher package, flag names may change – always re‑check.
2. Concurrency Control
The concurrency option limits how many browser instances Karma can start at once. In a container with 2 vCPUs and 2 GB RAM, setting concurrency: 2 keeps the host from thrashing.
module.exports = {
concurrency: 2
};
Higher concurrency speeds wall‑clock time but can expose flaky tests that share state or rely on local ports. Monitor logs for “port in use” errors or repeated failures to decide the sweet spot.
3. Worked Example: CI‑Ready Karma Config
Below is a minimal karma.conf.js that demonstrates both techniques. It runs tests in headless Chrome with sandbox disabled, limits concurrency to 2, and outputs JUnit XML for the CI dashboard.
module.exports = {
basePath: '',
frameworks: ['jasmine'],
files: [
'src/**/*.js',
'test/**/*.spec.js'
],
preprocessors: {
'src/**/*.js': ['coverage']
},
reporters: ['progress', 'junit'],
junitReporter: {
outputDir: 'reports',
outputFile: 'TESTS-unit.xml'
},
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox', '--disable-dev-shm-usage']
}
},
concurrency: 2,
logLevel: config.LOG_INFO,
singleRun: true
};
To validate:
- Run
karma --versionto confirm the Karma CLI version. - Execute
karma start --list-browsers– you should seeChromeHeadlessNoSandboxlisted. - Start the server with
karma startand watch the console for “Launching ChromeHeadlessNoSandbox” and for two simultaneous browser windows. - Check the
reportsfolder forTESTS-unit.xml.
4. Trade‑Offs and Limitations
- Adding flags is environment‑specific; a flag that works on Linux may break on Windows or macOS.
- Reducing concurrency lowers resource usage but increases total test time; balance depends on the team’s CI budget.
- Headless browsers without
--no-sandboxmay silently fail to launch in some CI images, leading to zero test coverage if you don’t check the logs. - Shared state between tests can surface only when multiple browsers run concurrently; consider adding
--single-processor isolating tests if flakiness persists.
Actionable Takeaway
1. Define custom launchers with the exact flags your CI needs.
2. Set concurrency to match the container’s CPU/memory budget.
3. Verify the configuration locally with karma --list-browsers and a minimal run.
4. Monitor CI logs for port or sandbox errors and adjust flags or concurrency accordingly.
With these steps, Karma will run reliably on any CI platform, delivering consistent results without touching your test suite.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.