RUNNING TESTS
Command Line
Karate v2 has a first-class CLI — karate run — alongside full Maven and Gradle integration via JUnit 6. Pick the entry point that fits your project; all three share the same underlying Runner API.
The familiar -Dkarate.options="..." and -Dkarate.env=... system-property overrides from v1 are supported in v2, so Maven/Gradle teams upgrading from v1 keep their "hard-code defaults in a Runner class, override from CI" workflow without code changes.
The karate run CLI
The simplest way to run tests — no Maven, no Gradle, no Java class needed. See Standalone Execution for installation.
# Run all features in a directory
karate run features/
# Run a single feature file
karate run features/users.feature
# Run a specific scenario by line number
karate run features/users.feature:25
# Run multiple paths (repeatable -P, or comma-separated --path a,b)
karate run -P features/smoke -P features/regression
# Filter by tag, 4 threads, QA environment
karate run -t @smoke -T 4 -e qa features/
Common Flags
| Flag | Description |
|---|---|
-P, --path <path> | Feature file or directory — repeatable and/or comma-separated |
-t, --tags <expr> | Tag expression (e.g. @smoke, ~@slow) — repeatable |
-T, --threads <n> | Parallel thread count |
-e, --env <name> | Karate environment (karate.env) |
-n, --name <name> | Scenario name filter (exact, whitespace-trimmed); bypasses tag filters |
-o, --output <dir> | Report output directory |
-g, --configdir <dir> | Directory containing karate-config.js |
-f, --format <formats> | Output formats: html, cucumber:json, junit:xml, karate:jsonl (prefix ~ to disable) |
-D, --dryrun | Parse but don't execute |
Run karate run --help for the full list.
Project File: karate-pom.json
For CLI users, karate-pom.json is a JSON project file that persists your run settings — analogous to pom.xml but for Karate. When present in the working directory, karate run loads it automatically.
{
"paths": ["classpath:com/comp/commission", "classpath:com/comp/statement"],
"tags": ["@smoke", "~@slow"],
"env": "qa",
"threads": 5,
"output": {
"dir": "target/karate-reports",
"cucumberJson": true
}
}
CLI flags override pom values. Use --no-pom to ignore it.
Maven Execution
Java teams use the karate-junit6 dependency and drive runs through a JUnit 6 test class. Standard mvn test discovers and runs them.
# Run all JUnit tests (including Karate runners)
mvn test
# Run a specific Karate runner class
mvn test -Dtest=UsersTest
# Run a specific test method
mvn test -Dtest=UsersTest#smokeTests
# Override the environment (karate.env)
mvn test -Dkarate.env=qa
# Override tags from CI without changing the Runner class
mvn test -Dtest=UsersTest -Dkarate.options="--tags @smoke"
# Multiple overrides in one string (v1-compatible)
mvn test -Dtest=UsersTest -Dkarate.options="--tags @smoke --env qa --threads 4"
JUnit 6 Runner Class
import io.karatelabs.junit6.Karate;
import org.junit.jupiter.api.DynamicNode;
class UsersTest {
@Karate.Test
Iterable<DynamicNode> testUsers() {
return Karate.run("classpath:users").relativeTo(getClass());
}
@Karate.Test
Iterable<DynamicNode> testSmoke() {
return Karate.run("classpath:users")
.tags("@smoke")
.threads(4)
.karateEnv("qa");
}
@Karate.Test
Iterable<DynamicNode> testMultiplePaths() {
return Karate.run("classpath:com/comp/commission", "classpath:com/comp/statement")
.tags("@smoke");
}
}
Karate.run(...) accepts varargs — use this when you want multiple paths baked into the Runner class. For ad-hoc overrides from CI without changing the class, use -Dkarate.options=... instead.
System-Property Overrides (CI pattern)
You do not need any wiring in your Runner class. Karate picks up these system properties automatically at parallel() time and overrides Builder values before the run:
| Sysprop | Env var fallback | Effect |
|---|---|---|
karate.options | KARATE_OPTIONS | Full option string using the karate run CLI grammar — paths, -P, tags, threads, env, -n, configdir, output, dryrun, formats |
karate.env | KARATE_ENV | Karate environment |
karate.config.dir | KARATE_CONFIG_DIR | Directory containing karate-config.js |
karate.output.dir | — | Report output directory |
Example — typical CI invocations against a runner that hard-codes defaults:
# Override one dimension
mvn test -Dtest=UsersTest -Dkarate.env=qa
# Override multiple in one karate.options string
mvn test -Dtest=UsersTest -Dkarate.options="--tags @smoke --threads 4 --env qa"
# Narrow to specific features for a rerun
mvn test -Dtest=UsersTest -Dkarate.options="classpath:features/login.feature:42"
Precedence (highest → lowest): karate.options sysprop > KARATE_OPTIONS env > individual karate.* sysprops > individual KARATE_* env vars > Runner.Builder values > karate-pom.json > defaults. If a malformed karate.options string is passed, it's logged at WARN and ignored — the run proceeds with Builder defaults.
Paths with spaces
The karate.options string is tokenized POSIX-shell-style, so inner quotes survive and whitespace is respected:
# Multiple paths that contain spaces — use -P with inner double quotes,
# and protect the whole sysprop value with outer single quotes
mvn test -Dtest=UsersTest '-Dkarate.options=-P "src/features/happy path" -P "src/features/edge cases"'
Single vs double quotes follow shell rules: single quotes around the -D... value stop the outer shell from interpreting the inner doubles; inside the sysprop value, double quotes group the path tokens with whitespace.
Gradle Execution
Gradle integration uses the same JUnit 6 runner class. Forward karate.* system properties to the test JVM so the overrides above work from the command line:
test {
useJUnitPlatform()
systemProperties System.properties.findAll { k, v ->
k.toString().startsWith('karate.')
}
outputs.upToDateWhen { false }
}
# Run all tests
./gradlew test
# Run a specific Karate runner class
./gradlew test --tests UsersTest
# Override environment
./gradlew test -Dkarate.env=staging
# Override tags and env from CI (no code change)
./gradlew test -Dkarate.options="--tags @smoke --env qa"
Filtering & Configuration
By Tag
Tag expressions work identically across CLI, Maven, and Gradle. ~ means "not". Comma means OR; repeated --tags means AND.
# Run scenarios tagged @smoke
karate run -t @smoke features/
# Exclude @slow
karate run -t ~@slow features/
# Either @smoke OR @regression
karate run -t @smoke,@regression features/
# @smoke AND @api
karate run -t @smoke -t @api features/
See Tags for expression syntax.
By Scenario Line or Name
# By line number — bypasses tag filters (great for debugging)
karate run features/users.feature:15
# By scenario name — exact match, trimmed on both sides.
# Stable under edits, so IDE plugins use this as a line-independent key.
karate run -n "Create user happy path" features/
# Combine with :LINE to narrow to one row of a Scenario Outline.
karate run -n "Parameterized check" features/outline.feature:9
Both forms bypass tag filters (@ignore, @env) — running a specific scenario always wins. Duplicate scenario names run every match. For a Scenario Outline, the name matches the outline itself and runs all rows.
By Environment
Set karate.env and read it in karate-config.js:
# CLI
karate run -e dev features/
# Maven
mvn test -Dtest=UsersTest -Dkarate.env=qa
# Gradle
./gradlew test -Dkarate.env=staging
function fn() {
var env = karate.env;
var config = { baseUrl: 'https://api-dev.example.com' };
if (env === 'qa') config.baseUrl = 'https://api-qa.example.com';
if (env === 'prod') config.baseUrl = 'https://api.example.com';
return config;
}
Development Patterns
Tight Iteration Loop
# Run one failing scenario by line
karate run features/problem.feature:15
# Run WIP tests locally
karate run -t @wip -e local features/
# Dry run — parse only, no HTTP
karate run -D features/
CI: Smoke then Full
# Fast smoke stage
karate run -t @smoke -T 4 -e ci features/
# Full suite
karate run -T 8 -e ci --format cucumber:json,junit:xml features/
Migrating from v1
Your v1 -Dkarate.options="..." invocations keep working in v2. The option string uses the same shape, and v2 adds a few new flags you can use inside it (notably -P, --path):
| v1 | v2 equivalent | Notes |
|---|---|---|
-Dkarate.options="classpath:features/users.feature" | Unchanged | Positional paths |
-Dkarate.options="features/a features/b" | Unchanged, or -Dkarate.options="-P features/a -P features/b" | -P is new in v2, handy when paths are awkward as positionals |
-Dkarate.options="--tags @smoke" | Unchanged | Tag filter |
-Dkarate.options="--dryrun" | Unchanged | Dry run |
-Dkarate.options="features/x.feature:25" | Unchanged | Line number targeting |
-Dkarate.env=qa | Unchanged | Individual env sysprop |
If you're building fresh instead of migrating, prefer the karate run CLI — one command, no JUnit runner class needed.
Common Gotchas
- Tag AND vs OR: comma is OR within one
-t, repeated-tis AND. - Path with line number bypasses tag filters — intentional, useful for IDE integrations.
- Gradle must forward system properties: see the
build.gradlesnippet above. workingDirvsoutput.dir: output is relative to process cwd, notworkingDir. Prefer absolute paths for reports in CI.karate.optionspaths replace Builder paths: when the sysprop contains paths, they fully replace any paths set in your Runner class (v1 parity). Use this intentionally for CI subsetting.
Next Steps
- Standalone Execution — install the
karateCLI - Parallel Execution — scale across threads
- Tags — expression syntax reference
- Test Reports — HTML, Cucumber JSON, JUnit XML, JSONL