Q23 of 40 · Karate

How would you debug a Karate scenario that fails with a confusing match error?

KarateMidkaratedebuggingmatchtroubleshootingapi-testing

Short answer

Short answer: Karate's match failure shows the actual vs expected diff with the exact path that failed. Add * print response to log the raw response before the match. Use match response contains rather than == to narrow which fields are wrong. The karate.log() function and * configure lowerCaseResponseHeaders = true help isolate header mismatches.

Detail

Step 1 — read the error message carefully: Karate's match failures show the path, actual value, and expected value:

path: $.name, actual: 'alice', expected: 'Alice'

Step 2 — print the raw response:

* print response
# or for a specific field:
* print 'name field is:', response.name

Step 3 — narrow with contains:

# Change == to contains to find which field fails
* match response contains { id: '#number' }   # does id exist?
* match response contains { name: 'Alice' }   # is name correct?

Step 4 — use karate.log():

* def debug = function() { karate.log('response body:', response); return true }
* call debug

Common causes of confusing match errors:

  • Trailing whitespace in string values: 'Alice ' vs 'Alice'
  • Integer vs String type: JSON field is "42" (string) but you're matching 42 (number)
  • Nested path typo: response.user.name vs response.users[0].name
  • Response is an array but you're matching as an object — check * print response.getClass()
  • Header case: Karate lowercases header names; use * configure lowerCaseResponseHeaders = true to align

// EXAMPLE

debug-example.feature

Feature: Debugging a failing match

  Scenario: Debug user response match failure
    * url 'https://api.example.com'
    Given path '/users/1'
    When  method GET
    Then  status 200

    # Step 1: print the full response to understand the structure
    * print 'Full response:', response

    # Step 2: use contains to isolate the failing field
    * match response contains { id: '#present' }   # does id exist?
    * match response contains { name: '#string' }  # is name a string?

    # Step 3: add type checks before value checks
    * match response.id   == '#number'   # verify type first
    * match response.name == '#string'   # then type of name
    * match response.name == 'Alice'     # then exact value

    # Step 4: check for whitespace issues
    * def trimmedName = response.name.trim()
    * match trimmedName == 'Alice'

// WHAT INTERVIEWERS LOOK FOR

Using * print before the failing match, narrowing with contains to isolate the problem field, and knowing the common causes of confusing failures (type mismatch, whitespace, array vs object). Systematic debugging rather than random config changes.

// COMMON PITFALL

Immediately editing the expected value to match the actual value without understanding why they differ. A mis-returned type (string vs number) or trailing whitespace indicates a server bug — fix the server, not the test.