Skip to main content

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

pom.xml — before (v1)
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-junit5</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
pom.xml — after (v2)
<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>
note

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.

pom.xml
<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 ClassStatus
com.intuit.karate.RunnerWorks — delegates to v2
com.intuit.karate.ResultsWorks — wraps v2 SuiteResult
com.intuit.karate.core.MockServerWorks — delegates to v2
com.intuit.karate.junit5.KarateWorks — 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 / logPrettyResponse
  • printEnabled
  • lowerCaseResponseHeaders
  • logModifier

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.comexample.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

Areav1v2
Primary driverWebDriver (chromedriver, etc.)Chrome DevTools Protocol (CDP)
Cross-browserVia WebDriverW3C WebDriver (chromedriver, geckodriver, safaridriver)
Browser poolingManual setupAutomatic via PooledDriverProvider
Auto-waitNot availableBuilt-in before element operations
showDriverLogWorkedNo 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
scope: 'caller' removed

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

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-junit5karate-junit6 dependency
  • Add explicit junit-jupiter dependency
  • Update Java version to 21+
  • Remove scope: 'caller' from driver config if present (no longer needed)
  • Replace delay(millis) with karate.pause(millis) if used before the driver starts
  • Replace JsonUtils with Json class (if used directly)
  • Remove code using WebSocketClient or 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.


Getting Help