FAQ
Frequently Asked Questions
Get quick answers to common questions about Karate installation, configuration, testing strategies, and troubleshooting.
Getting Started
What is Karate?
Karate is an open-source tool that combines API test automation, mocks, performance testing, and UI automation into a single unified framework. Tests are written in plain text using Gherkin syntax, making them readable by technical and non-technical team members.
Do I need programming knowledge to use Karate?
No. Karate tests use plain text with simple, readable syntax. Programming knowledge helps with advanced features like custom JavaScript functions and Java interop, but is not required for basic API testing.
Feature: Basic API test
Scenario: Get user information
Given url 'https://api.example.com'
And path 'users', 123
When method GET
Then status 200
And match response.name == 'John Doe'
How does Karate compare to other testing tools?
Karate offers a unified framework for API, UI, performance testing, and mocks. Unlike Cucumber, it requires no step definitions or glue code. Compared to Rest Assured, Karate provides simpler syntax with built-in assertions and debugging.
When to use Karate:
- Testing APIs and UIs together
- Teams with mixed technical skills
- Need built-in mocking capabilities
- Want unified test reporting
Consider alternatives:
- Pure frontend testing: Use Cypress or Playwright
- Java-heavy teams comfortable with code: Use Rest Assured
- High-volume load testing: Use JMeter or k6
- Mobile app testing: Use Appium directly
Installation & Setup
What Java version do I need?
Java 17 or higher is required as of Karate 1.4.0. Java 21 is recommended for best performance and modern JVM features.
# Check Java version
java -version
# Should show: java version "17.0.1" or higher
Version requirements:
- Karate 0.9.x - 1.3.x: Java 8+
- Karate 1.4.x+: Java 17+
Can I use Karate with Node.js projects?
Yes. Install Karate CLI via npm and integrate with your existing npm scripts and CI/CD pipelines.
# Global installation
npm install -g @karatelabs/karate-cli
# Run tests
karate test.feature
karate --threads 4 src/test/features
# Local installation
npm install --save-dev @karatelabs/karate-cli
{
"scripts": {
"test:api": "karate src/test/features",
"test:api:parallel": "karate --threads 4 src/test/features"
}
}
Project structure example:
my-node-project/
├── src/
│ └── app.js
├── test/
│ ├── unit/ # Jest/Mocha tests
│ └── api/ # Karate tests
│ ├── karate-config.js
│ └── features/
│ └── user-api.feature
└── karate-reports/
How do I fix Maven archetype issues behind a corporate proxy?
If Maven archetype commands fail behind a corporate proxy, temporarily disable your Maven settings.xml file or use the karate-core dependency with the all classifier.
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-core</artifactId>
<version>${karate.version}</version>
<classifier>all</classifier>
<scope>test</scope>
</dependency>
Add this to your pom.xml to keep .feature files with test classes:
<build>
<testResources>
<testResource>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
</build>
Gradle configuration:
sourceSets {
test {
resources {
srcDir file('src/test/java')
exclude '**/*.java'
}
}
}
Benefits:
- Keep
.featurefiles with test classes - Easier artifact management in one location
- No switching between
src/test/javaandsrc/test/resources
For more details, visit the Quick Start guide.
How do I set up VS Code for Karate?
Install the official Karate extension from the VS Code marketplace. Open a .feature file to activate syntax highlighting, autocomplete, and debugging features.
Extension features:
- Syntax highlighting for Gherkin
- Run scenarios directly from editor
- Step-through debugging
- IntelliSense for Karate keywords
API Testing
How do I handle authentication in tests?
Use the Background section to authenticate once and reuse the token across scenarios.
Feature: Protected API endpoints
Background:
Given url 'https://api.example.com'
And path 'auth/login'
And request { username: 'user', password: 'pass' }
When method POST
Then status 200
* def authToken = response.token
Scenario: Access protected resource
Given path 'protected-resource'
And header Authorization = 'Bearer ' + authToken
When method GET
Then status 200
How do I authenticate with OAuth 2.0 Client Credentials?
Create a reusable token feature and call it once using karate.callSingle():
Feature: Get OAuth token
Scenario: Get access token
Given url authUrl
And path 'oauth/token'
And form field grant_type = 'client_credentials'
And form field client_id = clientId
And form field client_secret = clientSecret
When method POST
Then status 200
* def accessToken = response.access_token
Configure in karate-config.js to run once and cache:
function fn() {
var config = {
authUrl: 'https://auth.example.com',
clientId: 'my-client',
clientSecret: 'my-secret'
};
// Get token once across all parallel tests
var auth = karate.callSingle('classpath:auth/get-token.feature', config);
config.accessToken = auth.accessToken;
return config;
}
Use in your feature files:
Background:
* header Authorization = 'Bearer ' + accessToken
How do I handle JWT token refresh?
Use karate.callSingle() with caching for tokens that expire:
function fn() {
// Cache token for 10 minutes (adjust based on token expiry)
karate.configure('callSingleCache', { minutes: 10 });
var auth = karate.callSingle('classpath:auth/login.feature');
return {
baseUrl: 'https://api.example.com',
accessToken: auth.token
};
}
For longer test runs, implement refresh logic in JavaScript:
function fn() {
var token = karate.get('accessToken');
var expiry = karate.get('tokenExpiry');
if (!token || Date.now() > expiry) {
var result = karate.call('classpath:auth/login.feature');
token = result.token;
karate.set('accessToken', token);
karate.set('tokenExpiry', Date.now() + (9 * 60 * 1000)); // 9 minutes
}
return token;
}
How do I test GraphQL APIs?
Use the text keyword to define GraphQL queries and send them as POST requests to the GraphQL endpoint.
Scenario: Query user data
Given url 'https://api.example.com/graphql'
And text query =
"""
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
"""
And request { query: '#(query)', variables: { id: '123' } }
When method POST
Then status 200
And match response.data.user.name == '#string'
Can I test file uploads?
Yes. Karate supports multipart file uploads with the multipart keyword.
Scenario: Upload PDF file
Given url 'https://api.example.com/upload'
And multipart file myFile = { read: 'test-file.pdf', filename: 'test.pdf', contentType: 'application/pdf' }
And multipart field message = 'Test upload'
When method POST
Then status 200
Data Management
How do I read test data from files?
Use the read function to load data from JSON, CSV, XML, or YAML files.
Scenario: Use external test data
* def userData = read('test-data/users.json')
* def user = userData[0]
# Read CSV data
* def csvData = read('test-data/users.csv')
Given url 'https://api.example.com'
And path 'users'
And request user
When method POST
Then status 201
Can I use databases in tests?
Yes. Access databases through Java interop or by calling HTTP endpoints that query your database.
Scenario: Query database via HTTP
Given url 'http://localhost:8080/db'
And path 'query'
And request { sql: 'SELECT * FROM users WHERE id = ?', params: [123] }
When method POST
Then status 200
* def dbResult = response.data[0]
How does Karate handle different data formats?
Karate natively supports JSON, XML, CSV, YAML, and binary data formats.
Scenario: Work with multiple formats
# JSON (native support)
* def user = { name: 'John', age: 30 }
* def users = read('users.json')
# XML (native support)
* def xmlData = <user><name>John</name></user>
* match xmlData/user/name == 'John'
# CSV (automatic conversion)
* def csvData = read('users.csv')
* def firstUser = csvData[0]
# YAML (automatic conversion)
* def config = read('config.yaml')
# Binary data
* def imageBytes = karate.readAsBytes('test-image.png')
Variables & Configuration
How do I use variables in karate-config.js?
Variables in karate-config.js must be returned in the config object to be available in feature files.
function fn() {
var env = karate.env || 'dev';
var config = {
baseUrl: 'https://' + env + '.api.example.com',
timeout: 5000,
adminUser: 'admin@test.com',
apiVersion: 'v2'
};
// Environment-specific overrides
if (env === 'prod') {
config.baseUrl = 'https://api.example.com';
}
return config; // All properties become available as variables
}
Use these variables directly in your feature files:
Given url baseUrl
And path apiVersion, 'users'
How does variable scope work with def?
Variables defined with def are scoped to the current scenario. Use Background for shared setup across scenarios in the same feature.
Feature: Variable scope example
Background:
* def sharedVar = 'available in all scenarios'
* url baseUrl
Scenario: First test
* def localVar = 'only in this scenario'
* print sharedVar
* print localVar
Scenario: Second test
* print sharedVar
# localVar is not available here - defined in different scenario
For one-time setup across multiple features, use karate.callSingle() in karate-config.js:
function fn() {
var auth = karate.callSingle('classpath:auth/login.feature');
return {
baseUrl: 'https://api.example.com',
authToken: auth.token
};
}
How do I set dynamic data in request bodies?
Use embedded expressions #() to insert variable values into JSON:
Scenario: Dynamic request body
* def userId = 123
* def timestamp = java.lang.System.currentTimeMillis()
# Method 1: Embedded expressions
Given request { id: '#(userId)', created: '#(timestamp)' }
When method POST
Then status 201
# Method 2: Build object in JavaScript
* def body = { id: userId, created: timestamp, name: 'Test' }
Given request body
When method POST
Then status 201
Test Execution
How do I run tests in parallel?
Use the JUnit 5 runner with the parallel method to specify thread count.
@Test
void testParallel() {
Results results = Runner.path("classpath:features")
.tags("@regression")
.parallel(5); // 5 parallel threads
assertEquals(0, results.getFailCount());
}
How do I skip tests conditionally?
Use the karate.abort function to skip tests based on environment or configuration.
Background:
* def skipTest = karate.env == 'production'
* karate.abort(skipTest)
Scenario: Development only test
Given path 'debug/endpoint'
When method GET
Then status 200
Can I generate test reports?
Yes. Karate automatically generates detailed HTML reports in the target/karate-reports/ directory with timeline views, detailed logs, and pass/fail statistics.
Report formats:
- HTML (interactive reports)
- JSON (machine-readable)
- JUnit XML (CI/CD integration)
Performance & Mocking
Can I do performance testing?
Yes. Karate integrates with Gatling for performance testing through the performance hook API.
@Test
void performanceTest() {
PerfHook hook = new PerfHook("classpath:perf/load-test.js");
Results results = Runner.path("classpath:features/api")
.hook(hook)
.parallel(10);
}
How do I create mock services?
Use karate.start to start a mock server from a feature file.
Feature: Mock server
Background:
* def port = karate.start('user-mock.feature').port
* url 'http://localhost:' + port
Scenario: Mock returns user data
Given path 'users', 1
When method GET
Then status 200
And match response == { id: 1, name: 'John Doe' }
Troubleshooting
Common Errors
How do I fix NoClassDefFoundError with Maven Surefire?
This error occurs when Maven Surefire plugin version conflicts with JUnit 5 or Karate dependencies.
Solution: Update your pom.xml with compatible versions:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
For dependency conflicts, use the all classifier which bundles all dependencies:
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-core</artifactId>
<version>${karate.version}</version>
<classifier>all</classifier>
<scope>test</scope>
</dependency>
How do I fix "ReferenceError: variable is not defined"?
This GraalVM/Polyglot error means a variable used in your feature file was never declared or returned from configuration.
Common causes:
- Variable not returned from
karate-config.js - Typo in variable name (names are case-sensitive)
- Variable defined in a different scope
Solution: Ensure your karate-config.js returns all required variables:
function fn() {
var config = {
baseUrl: 'https://api.example.com', // Must match exact name used in features
timeout: 5000
};
return config;
}
Use the exact variable name in your feature file:
Given url baseUrl # Correct - matches config
Given url BaseURL # Wrong - case mismatch causes error
How do I fix "javascript evaluation failed" errors?
This occurs when Karate's JavaScript engine cannot parse your code.
Common causes:
- Syntax errors in JavaScript files
- Using ES6+ features not supported by GraalJS
- Missing return statement in functions
Solution: Ensure your JavaScript files use standard function syntax:
function fn(arg) {
// Your logic here
return result; // Must return a value
}
Avoid ES6 arrow functions in separate .js files:
// Don't use arrow functions in .js files
const fn = (arg) => arg * 2; // May fail
// Use standard function syntax instead
function fn(arg) {
return arg * 2;
}
How do I fix ClassNotFoundException in VS Code?
This occurs when VS Code cannot find your Java classes or Karate dependencies.
Solutions:
-
Reload the window: Press
Cmd+Shift+P(Mac) orCtrl+Shift+P(Windows), type "Reload Window" -
Clean and rebuild:
mvn clean compile test-compile
- Check your project structure: Ensure
.featurefiles are in the correct location:
src/test/java/
└── mypackage/
├── MyTest.java
└── my.feature
- Update the VS Code Karate extension to the latest version
How do I fix Nashorn null errors?
Nashorn was replaced by GraalJS in Karate 1.0+. This error indicates version incompatibility.
Solution: Upgrade to Karate 1.4+ and Java 17+:
<dependency>
<groupId>io.karatelabs</groupId>
<artifactId>karate-junit5</artifactId>
<version>1.5.0</version>
<scope>test</scope>
</dependency>
If you must use older Java versions, stay on the Karate 0.9.x series.
How do I fix "Access to host class is not allowed"?
GraalJS restricts access to Java classes by default for security. This error occurs when using incorrect syntax for Java interop.
Solution: Use the correct Java.type() syntax:
# Correct way to access Java classes
* def UUID = Java.type('java.util.UUID')
* def id = UUID.randomUUID() + ''
# For your own classes - must be on classpath with public methods
* def MyUtils = Java.type('com.mycompany.MyUtils')
* def result = MyUtils.doSomething()
How do I fix "RuntimeException: not found: features"?
The Karate runner cannot locate your feature files.
Solution: Check your runner class path configuration:
@Karate.Test
Karate testAll() {
return Karate.run()
.relativeTo(getClass()); // Looks for features relative to this class
}
Ensure your file structure matches:
src/test/java/
└── mypackage/
├── MyRunner.java # Runner class
└── features/
└── my.feature # Feature files
Or specify an explicit path:
return Karate.run("classpath:features").relativeTo(getClass());
My tests are failing intermittently
Common causes include timing issues, test data dependencies, and environment differences.
Solutions:
- Timing issues: Add waits or increase timeouts
Background:
* configure readTimeout = 30000
* retry until responseStatus == 200
- Test data dependencies: Use unique identifiers
Background:
* def uniqueId = java.util.UUID.randomUUID()
- Environment differences: Use proper configuration
// karate-config.js
if (env === 'ci') {
config.readTimeout = 60000;
}
How do I debug failing tests?
Enable detailed logging and response printing with configuration options.
Background:
* configure logPrettyResponse = true
* configure printEnabled = true
Scenario: Debug failing test
Given url 'https://api.example.com'
And path 'users', 1
When method GET
* print 'Response:', response
Then status 200
Tests work locally but fail in CI
Ensure CI uses the correct environment configuration and has adequate timeouts for slower environments.
# GitHub Actions example
- name: Run Tests
run: mvn test -Dkarate.env=ci
Common solutions:
- Verify environment configuration matches CI
- Increase timeouts for slower CI environments
- Ensure all required services are running
- Use test-specific data or mocks
Integration & Advanced
Can I integrate with Cucumber reports?
Yes. Karate generates Cucumber-compatible JSON reports.
Results results = Runner.path("classpath:features")
.outputCucumberJson(true)
.parallel(5);
How do I call Java code from Karate?
Use the Java.type function to access Java classes and call methods.
Scenario: Call Java utility
* def JavaUtils = Java.type('com.mycompany.JavaUtils')
* def result = JavaUtils.processData('input-data')
* match result == 'expected-output'
# Call static methods
* def uuid = java.util.UUID.randomUUID() + ''
Can I use custom assertions?
Yes. Create JavaScript functions in karate-config.js and use them in tests.
// karate-config.js
function customAssert(actual, expected) {
return actual.toLowerCase() === expected.toLowerCase();
}
return { customAssert: customAssert };
Scenario: Use custom assertion
* assert customAssert(response.name, 'JOHN DOE')
Community & Support
Where can I get support?
Free community support:
- Stack Overflow: Ask questions with the karate tag
- GitHub: Report issues
Enterprise support:
- Professional services and architecture design
- Priority support with SLA guarantees
- Corporate training programs
- Custom feature development
Is Karate suitable for enterprise use?
Yes. Karate is widely adopted by Fortune 500 companies and large enterprises for production environments with high transaction volumes.
Enterprise benefits:
- Robust parallel execution and distributed testing
- Comprehensive reporting for audit and compliance
- Built-in support for OAuth, SAML, and mutual TLS
- Reduces tool sprawl with unified API, UI, performance, and mock testing
How can I contribute to Karate?
Contribute through code improvements, documentation, community support, or testing beta releases.
Ways to contribute:
- Submit pull requests with tests and clear descriptions
- Fix documentation typos or add examples
- Answer questions on Stack Overflow
- Test beta releases and provide feedback
Best Practices
What are common anti-patterns to avoid?
Avoid heavy setup in Background, testing implementation details, hardcoding environment values, and creating overly complex tests.
Anti-pattern: Heavy setup in Background
# DON'T
Background:
* call read('create-100-users.feature')
* call read('setup-complex-data.feature')
Better approach: Use callonce
# DO
Background:
* def testData = callonce read('lightweight-setup.feature')
Anti-pattern: Hardcoded environment values
# DON'T
Given url 'https://prod-api.company.com'
Better approach: Use configuration
# DO
Given url baseUrl
When should I NOT use Karate?
Karate is not ideal for pure unit testing, frontend-only testing, non-HTTP protocols, or mobile app testing.
Better alternatives:
- Unit tests: JUnit 5, TestNG, Jest
- UI-only tests: Cypress, Playwright
- Load testing: JMeter, k6, Artillery
- Mobile testing: Appium, Detox, Espresso
- Keep tests focused with single responsibility
- Use
calloncefor expensive setup operations - Test behavior, not implementation details
- Configure environment-specific values in
karate-config.js
Next Steps
- Get started quickly: Quick Start
- Learn core concepts: Feature Files
- Explore advanced features: Java API
- Set up your IDE: VS Code
- Run tests efficiently: Parallel Execution