Choosing Karma’s autoWatch vs singleRun: A Practical Guide for Local vs CI Test Runs
When developing locally you want instant feedback, but CI needs deterministic runs. This blog explains how to use Karma’s autoWatch and singleRun settings, gives a minimal config that switches automatically, and discusses trade‑offs.
12 Aug 2025, 22:10 UTC

The Problem
In most JavaScript projects the test runner is Karma. Developers often want a live feedback loop: as soon as they edit a file, the test suite should re‑run. Continuous Integration (CI) pipelines, on the other hand, need a single, deterministic execution that exits when finished. Choosing the wrong mode can lead to slow local builds or flaky CI jobs.
Why autoWatch and singleRun Matter
Karma exposes two complementary flags:
autoWatch– whentrue, Karma watches the file system and re‑runs tests on each change. This is ideal for day‑to‑day development.singleRun– whentrue, Karma runs the suite once and exits. This is the default for CI because it guarantees a clean process and deterministic exit status.
Using the wrong flag in the wrong context can have tangible effects: a local autoWatch run that never stops can consume memory; a CI job that relies on autoWatch will never finish, causing pipelines to hang.
Configuring autoWatch
To enable continuous watching locally, set autoWatch: true and singleRun: false in your karma.conf.js. The default Karma command (karma start) will then stay alive, listening for file changes.
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: ['src/**/*.js', 'test/**/*.spec.js'],
autoWatch: true,
singleRun: false,
browsers: ['ChromeHeadless'],
reporters: ['progress']
});
};
When you edit a .spec.js file, Karma will automatically re‑run the affected tests and print progress in the terminal.
Configuring singleRun
For CI, you want the process to exit after completing the suite. Set singleRun: true and autoWatch: false. In most CI scripts you can override this with a CLI flag:
karma start --singleRun
When singleRun is true, Karma will run the suite once, generate coverage reports if configured, and exit with a status code reflecting test success.
A Unified Config Example
Rather than maintaining two separate config files, you can let Karma read an environment variable. The following snippet toggles between development and CI automatically:
module.exports = function(config) {
const isCi = process.env.CI === 'true';
config.set({
frameworks: ['jasmine'],
files: ['src/**/*.js', 'test/**/*.spec.js'],
autoWatch: !isCi,
singleRun: isCi,
browsers: ['ChromeHeadless'],
reporters: ['progress', 'coverage'],
coverageReporter: {
type: 'lcov',
dir: 'coverage/'
}
});
};
In local development you simply run karma start. In CI, set CI=true in the environment and run karma start or karma start --singleRun to override the flag.
Trade‑offs and Limitations
- Resource Consumption:
autoWatchkeeps the Karma process alive and consumes memory/CPU, which can become noticeable in large test suites. - Missing Change‑Driven Bugs: A
singleRunCI job will not surface bugs that only appear after a specific file change unless you run a full watch cycle in a pre‑CI build step. - Reporter Buffering: Some reporters (e.g.,
coverage) buffer output until the process exits. RunningautoWatch=truewill delay coverage report generation until you stop the process. - File Inclusion: Ensure every test and source file is listed in the
filesarray. If a file is omitted,autoWatchwill not detect changes to it.
Actionable Takeaway
Use a single karma.conf.js that toggles autoWatch and singleRun based on an environment variable (e.g., CI). This guarantees:
- Instant feedback during local development.
- Deterministic, non‑interactive runs in CI.
- Consistent configuration across teams and environments.
Before merging, run:
# Verify CI mode
karma start --singleRun
# Verify local watch mode
karma start
# Edit a test file and observe re‑run
With this pattern you avoid the pitfalls of mis‑configured test runs and keep both developers and CI pipelines happy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.