Skip to main content

RUNNING TESTS

Debugging

Debug tests quickly using print statements, IDE breakpoints, and built-in inspection tools—no external debuggers required.

Benefits of Karate Debugging​

  • Zero setup: No external debugger installation or configuration needed
  • Built-in pretty printing: Automatic JSON/XML formatting for readability
  • IDE integration: Native support for VS Code and IntelliJ breakpoints
  • Always visible output: Print statements appear in console and HTML reports
  • No performance overhead: Debug features don't slow down production test runs

Simple Print Debugging​

Start with the most straightforward approach—print statements for quick inspection.

Gherkin
Feature: Quick debugging

Scenario: Debug with print
* def baseUrl = 'https://jsonplaceholder.typicode.com'
* def user = { id: 1, name: 'Alice' }
* print 'Testing user:', user.name

Given url baseUrl + '/users/' + user.id
* print 'Request URL:', baseUrl + '/users/' + user.id
When method get

* print 'Status:', responseStatus
* print 'Response time:', responseTime, 'ms'
Then status 200

Variable Inspection​

Use built-in functions to inspect complex data structures and understand test state.

Gherkin
Feature: Variable Inspection

Scenario: Debug complex objects
* def order =
"""
{
id: 'ord_123',
items: [
{ name: 'Laptop', price: 999 },
{ name: 'Mouse', price: 49 }
],
total: 1048
}
"""

# Pretty print for readability
* print 'Order data:\n', karate.pretty(order)

# Inspect object structure
* print 'Available keys:', karate.keysOf(order)
* print 'Items count:', order.items.length

# Type checking
* print 'Order type:', karate.typeOf(order)
* print 'Total type:', karate.typeOf(order.total)
Logging Methods Comparison

All three logging methods write to both the console (via SLF4J karate.scenario category) and the HTML report:

MethodLevelBest for
printINFOQuick debugging — Gherkin keyword, supports comma-separated values
karate.log()INFOLogging from JavaScript — accepts multiple arguments
karate.logger.debug/info/warn/error()VariesLevel-aware logging — use when you need to control verbosity

Configure console visibility via your SLF4J binding (e.g., logback.xml) using the karate.scenario logger category.

IDE Debugging​

VS Code Breakpoints​

Set breakpoints in JavaScript functions and step through code execution.

Gherkin
Feature: VS Code debugging

Background:
* def calculateDiscount =
"""
function(price, isVip) {
var discount = 0;
if (isVip) {
discount = price * 0.15; // Set breakpoint here
} else {
discount = price * 0.05;
}
return discount;
}
"""

Scenario: Debug discount calculation
* def price = 100
* def isVip = true
* def discount = calculateDiscount(price, isVip)
* match discount == 15

IntelliJ Integration​

Debug tests directly from IntelliJ using JUnit integration.

Java
@Test
void debugInIntelliJ() {
// Right-click and select "Debug"
Karate.run("problematic-feature")
.karateEnv("dev")
.relativeTo(getClass());
}

Debug Strategies​

Isolate the Problem​

Narrow down issues by testing components independently.

Gherkin
Feature: Problem Isolation

@debug
Scenario: Test step by step
# Step 1: Verify environment configuration
* print 'Environment:', karate.env
* def baseUrl = 'https://jsonplaceholder.typicode.com'
* print 'Base URL:', baseUrl

# Step 2: Test connectivity
Given url baseUrl + '/posts'
When method get
* print 'Connectivity check status:', responseStatus
Then status 200

# Step 3: (Optional) Test authentication
# * call read('authenticate.feature')
# * print 'Auth token valid:', authToken != null

# Step 4: Test target endpoint
Given url baseUrl
And path 'users'
When method get
* print 'Endpoint status:', responseStatus
Then status 200

Step-by-Step Analysis​

HTTP request/response bodies are pretty-printed by default and captured at INFO into reports. To also see them on the console, drop the SLF4J level to TRACE for this run (e.g. --log-console trace) — or use configure logging from inside a feature for finer scoping. See Logging for the full picture.

Gherkin
Feature: Detailed request/response logging

Scenario: Analyze HTTP traffic
# default: pretty bodies are already on
* configure logging = { console: 'trace' } # show full bodies on console too

* def baseUrl = 'https://jsonplaceholder.typicode.com'
* def userData = { name: 'Alice', email: 'alice@example.com' }
* print 'Sending data:\n', karate.pretty(userData)

Given url baseUrl
And path 'users'
And request userData
* print 'Full URL:', baseUrl + '/users'

When method post
* print 'Response time:', responseTime, 'ms'

Then status 201
* print 'Created user:\n', karate.pretty(response)

Debugging Parallel Tests

Set .parallel(1) in your test runner to execute sequentially when debugging. Parallel execution interleaves print statements, making output hard to follow.

Common Debugging Patterns​

Debug Authentication Flows​

Track authentication through multiple steps to identify where it breaks.

Gherkin
Feature: Debug Authentication

Scenario: Debug login flow
* def baseUrl = 'https://jsonplaceholder.typicode.com'

# Step 1: Request auth token (simulated)
* print 'Step 1: Request auth token'
Given url baseUrl
And path 'posts'
And request { username: 'alice', password: 'secret' }
When method post
* print 'Login status:', responseStatus

# Simulate token creation for demonstration
* def token = 'fake-jwt-token-12345'
* print 'Token received:', token

# Step 2: Use token for authorized request
* print 'Step 2: Use token for API call'
Given url baseUrl
And path 'users', 1
And header Authorization = 'Bearer ' + token
When method get
* print 'Authenticated request status:', responseStatus
Then status 200

Debug JSON Path Issues​

Understand why JSON path expressions fail by inspecting data structure.

Gherkin
Feature: Debug JSON path

Scenario: Troubleshoot path expressions
* def response = { data: { users: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] } }

# Debug step by step
* print 'Full response:', karate.pretty(response)
* print 'Data level:', response.data
* print 'Users array:', response.data.users
* print 'First user:', response.data.users[0]

# Test JSON path
* def result = karate.jsonPath(response, '$.data.users[?(@.id==1)]')
* print 'JSON path result:', result
* match result[0].name == 'Alice'

Debug Match Failures​

Get detailed information when assertions fail.

Gherkin
Feature: Debug match failures

Scenario: Understand match errors
* def actual = { id: 123, name: 'Alice', role: 'admin', extra: 'field' }
* def expected = { id: '#number', name: '#string' }

# Use karate.match for detailed error info
* def matchResult = karate.match(actual, expected)
* if (!matchResult.pass) print 'Match failed:', matchResult.message

# Use contains for partial matching
* match actual contains expected
* print 'Partial match succeeded'

# Debug exact match failure
* print 'Actual keys:', karate.keysOf(actual)
* print 'Expected keys:', karate.keysOf(expected)

Log Configuration​

Basic Logback Setup​

Create logback-test.xml in src/test/resources for detailed logging.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- Debug level for Karate (use karate.http, karate.mock, etc. for fine-grained control) -->
<logger name="io.karatelabs" level="DEBUG"/>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

Log Levels​

  • DEBUG: Complete request/response payloads, perfect for troubleshooting
  • INFO: Basic execution information, good for normal test runs
  • WARN: Warnings and timeouts only
  • ERROR: Failures and exceptions only

Debug Tools and Utilities​

Built-in Functions​

Gherkin
Feature: Debug utilities

Scenario: Use Karate debug functions
* def data = { nested: { value: 'test', count: 42 } }

# Pretty print JSON
* print karate.pretty(data)

# Get object keys
* print karate.keysOf(data)
* print karate.keysOf(data.nested)

# Type checking
* print karate.typeOf(data)
* print karate.typeOf(data.nested.count)

# Size/length
* def array = [1, 2, 3, 4, 5]
* print 'Array length:', array.length

Conditional Debug Output​

Enable debug output only when needed using environment variables.

Gherkin
Feature: Conditional debugging

Background:
* def debug = karate.properties['debug'] == 'true'
* def debugLog = function(msg, data) { if (debug) karate.log(msg, data) }

Scenario: Conditional logging
* debugLog('Starting test with user', { id: 123 })

Given url baseUrl
And path 'users/123'
When method get

* debugLog('Response received', response)
Then status 200

Error Message Analysis​

Common error patterns and how to debug them:

JSON Path Errors​

Error: $.user.id path not found

Debug:

* print 'Full response:', karate.pretty(response)
* print 'Response keys:', karate.keysOf(response)

Connection Failures​

Error: Connection timeout or refused

Debug:

* print 'Target URL:', baseUrl
* print 'Response status:', responseStatus
* configure connectTimeout = 30000
* configure readTimeout = 30000

Assertion Failures​

Error: Match failed for complex object

Debug:

* print 'Expected:', expected
* print 'Actual:', actual
* def diff = karate.match(actual, expected)
* print 'Match result:', diff

Next Steps​

Master debugging and continue with related topics: