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)
Print vs Log

Use print for always-visible output in console and reports. Use karate.log() for debug-level messages that can be suppressed via logging configuration.

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

Enable detailed logging to see exactly what Karate sends and receives.

Gherkin
Feature: Detailed request/response logging

Scenario: Analyze HTTP traffic
* configure logPrettyRequest = true
* configure logPrettyResponse = true

* 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 -->
<logger name="com.intuit.karate" 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: