Q11 of 40 · Karate

How do you reuse logic across scenarios with Karate (helpers and library features)?

KarateMidkaratehelpersreusefeature-compositiondry

Short answer

Short answer: Extract common steps into a helper feature under helpers/ and call it with * def result = call read('classpath:helpers/create-user.feature') { email: 'test@example.com' }. For JavaScript utilities, define them in a .js file and import with * def utils = read('classpath:helpers/utils.js'). Both patterns enable DRY reuse without duplicating steps.

Detail

Karate has two complementary reuse mechanisms:

Feature helpers — for HTTP actions (create data, login, call sub-APIs):

src/test/resources/
  helpers/
    login.feature
    create-user.feature
    create-order.feature
  users/
    get-user.feature
    update-user.feature

Helpers are called with call read and return variables via * def at the end of their Scenario:

# helpers/create-user.feature
Scenario:
  Given url baseUrl
  And   path '/users'
  And   request { name: '#(name)', email: '#(email)' }
  When  method POST
  Then  status 201
  * def id    = response.id
  * def email = response.email

JavaScript libraries — for data transformation, date utilities, random generators:

* def utils = read('classpath:helpers/utils.js')
* def uniqueEmail = utils.generateEmail('alice')

callonce for expensive helpers that should run once per suite (e.g., seeding reference data or fetching an access token).

Java helpers — for complex logic that's hard to express in JS or the DSL:

* def MyHelper = Java.type('com.example.test.MyHelper')
* def result = MyHelper.generateHmacSignature(payload, secret)

// EXAMPLE

helpers/create-product.feature

# helpers/create-product.feature
# Arguments received: name, price, category
Feature: Create product helper

  Scenario:
    Given url baseUrl
    And   path '/products'
    And   header Authorization = 'Bearer ' + adminToken
    And   request { name: '#(name)', price: '#(price)', category: '#(category)' }
    When  method POST
    Then  status 201
    * def productId = response.id
    * def productSlug = response.slug

# Caller feature:
# * def prod = call read('classpath:helpers/create-product.feature')
#     { name: 'Widget', price: 9.99, category: 'tools' }
# * def productId = prod.productId
# Then use productId in subsequent assertions

// WHAT INTERVIEWERS LOOK FOR

Structuring the helpers/ folder, the pattern of exporting variables from helpers via * def, and knowing when to use a feature helper vs a JS utility vs a Java class. The distinction between call and callonce is a practical detail.

// COMMON PITFALL

Duplicating the same Given/When/Then login steps across 20 feature files instead of extracting a login.feature helper. This is the most common DRY violation in Karate codebases.