GET STARTED
Migration from v1
Karate v2 includes backward compatibility shims that allow most v1 code to work with minimal changes. For most users, the only change required is updating the Maven dependency.
Quick Start
Step 1: Update Maven Dependencies
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-junit5</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-junit6</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
Unlike karate-junit5 which bundled JUnit, karate-junit6 declares JUnit as a provided dependency, giving you control over the JUnit version. You must add junit-jupiter explicitly.
Reference: See the karate-demo migration commit for a complete example of dependency changes.
Step 2: Update Java Version
Karate v2 requires Java 21+ for virtual threads support.
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
That's it for most projects. Run your tests and they should work.
V1 Compatibility Shims
The following v1 APIs work without code changes via deprecated shims:
| v1 Class | Status |
|---|---|
com.intuit.karate.Runner | Works — delegates to v2 |
com.intuit.karate.Results | Works — wraps v2 SuiteResult |
com.intuit.karate.core.MockServer | Works — delegates to v2 |
com.intuit.karate.junit5.Karate | Works — delegates to v2 |
Example: Runner API (no changes needed)
// This v1 code works in v2 without modification
import com.intuit.karate.Results;
import com.intuit.karate.Runner;
Results results = Runner.path("classpath:features")
.tags("~@ignore")
.parallel(5);
assertTrue(results.getFailCount() == 0, results.getErrorMessages());
Example: MockServer API (no changes needed)
// This v1 code works in v2 without modification
import com.intuit.karate.core.MockServer;
MockServer server = MockServer
.feature("classpath:mock.feature")
.arg("key", "value")
.http(0).build();
Gradual Migration to v2 APIs
Each shim provides a toV2*() method if you want to migrate incrementally:
// Get underlying v2 Builder
io.karatelabs.core.Runner.Builder v2Builder = v1Builder.toV2Builder();
// Get underlying v2 MockServer
io.karatelabs.core.MockServer v2Server = v1Server.toV2MockServer();
// Get underlying v2 SuiteResult
io.karatelabs.core.SuiteResult v2Results = v1Results.toSuiteResult();
Deprecated Configure Options
These configure options now produce a warning and have no effect:
logPrettyRequest/logPrettyResponseprintEnabledlowerCaseResponseHeaderslogModifier
Your tests will still pass — these are just no-ops now.
Feature File Compatibility
Most feature files work unchanged. The only known difference:
- Cookie domain assertions: RFC 6265 compliance means leading dots are stripped (
.example.com→example.com)
Browser Automation (UI Tests)
V2 uses a rewritten driver with CDP as the primary backend and full W3C WebDriver support for cross-browser testing. The Gherkin syntax is unchanged:
* driver serverUrl + '/login'
* input('#username', 'admin')
* click('button[type=submit]')
* waitFor('#dashboard')
* match driver.title == 'Welcome'
Key Differences from v1
| Area | v1 | v2 |
|---|---|---|
| Primary driver | WebDriver (chromedriver, etc.) | Chrome DevTools Protocol (CDP) |
| Cross-browser | Via WebDriver | W3C WebDriver (chromedriver, geckodriver, safaridriver) |
| Browser pooling | Manual setup | Automatic via PooledDriverProvider |
| Auto-wait | Not available | Built-in before element operations |
showDriverLog | Worked | No effect (TODO) |
Driver in Called Features
V2 preserves v1 behavior: if a called feature creates a driver via a shared-scope call (* call read('feature')), the driver automatically propagates back to the caller. No special configuration is needed.
# login.feature — driver propagates to caller automatically
@ignore
Feature: Login
Background:
* configure driver = { type: 'chrome' }
Scenario: Login
* driver serverUrl + '/login'
* input('#username', 'admin')
* click('#submit')
* waitFor('#dashboard')
# main.feature — driver is available after call returns
Scenario: Full regression
* call read('classpath:pages/login.feature')
* delay(5000) # ✅ works — driver propagated from login
* call read('classpath:pages/dashboard.feature') # ✅ works — driver is shared
Early v2 releases required scope: 'caller' in the driver config for this to work. This is no longer needed and can be safely removed.
Driver-Bound Functions
These functions only work after driver 'url' has been called: click(), input(), delay(), submit(), waitFor(), screenshot(), script(), mouse(), keys(), etc.
If you see <function> is not defined, check that the driver was initialized before that line. For a delay without a driver, use karate.pause(millis) instead.
Browser Pooling (New Default)
V2 automatically pools browser instances — no configuration needed:
Runner.path("features/")
.parallel(4); // Pool of 4 drivers auto-created
Recommended Patterns for UI Test Reuse
Pattern 1: Caller owns the driver (recommended for new projects)
# main.feature — driver starts here
Background:
* configure driver = { type: 'chrome' }
Scenario: Full flow
* driver serverUrl + '/login'
* call read('classpath:pages/login-steps.feature')
* call read('classpath:pages/dashboard-steps.feature')
Called features just perform actions — no driver init needed. This is the cleanest approach.
Pattern 2: Called feature starts the driver (v1-style)
Called features that create a driver will automatically propagate it back to the caller. This works out of the box — no extra configuration needed. See Driver in Called Features above.
Migration Checklist
- Update
karate-junit5→karate-junit6dependency - Add explicit
junit-jupiterdependency - Update Java version to 21+
- Remove
scope: 'caller'from driver config if present (no longer needed) - Replace
delay(millis)withkarate.pause(millis)if used before the driver starts - Replace
JsonUtilswithJsonclass (if used directly) - Remove code using
WebSocketClientor Driver Java APIs (if used) - Update cookie domain assertions if needed
Reference Migration Commits
karate-demo
Commit: c8fca97ce
This involved additional infrastructure changes beyond what typical end-users need:
- Spring Boot 2.x → 3.x upgrade (required for Java 21)
javax.*→jakarta.*servlet imports- Spring Security 5 → 6 configuration style
- Cookie domain normalization for RFC 6265 compliance
karate-e2e-tests
Commit: 7ffe47509
A simpler migration focused on test dependencies and runner changes.