Q19 of 40 · Karate

How do you structure a Karate project (folders, naming, configuration files)?

KarateMidkarateproject-structureorganisationkarate-configbest-practices

Short answer

Short answer: Place the JUnit runner in src/test/java. Under src/test/resources: karate-config.js at root for environment config, feature files grouped by service domain, helpers/ for reusable features, mocks/ for stub definitions, and data/ for JSON test fixtures. The runner discovers all .feature files under the specified classpath.

Detail

Standard Karate project layout:

src/
  test/
    java/
      com/example/
        SuiteRunner.java          ← JUnit 5 parallel runner
    resources/
      karate-config.js            ← environment variables, base URL, auth
      logback-test.xml            ← logging config for test run
      features/
        users/
          create-user.feature
          get-user.feature
          update-user.feature
        orders/
          checkout.feature
          order-status.feature
      helpers/
        login.feature             ← reusable: called with callonce
        create-user.feature       ← reusable: test data setup
        get-token.feature
        utils.js                  ← JavaScript utilities
      mocks/
        payment-gateway.feature   ← Karate Mock stub definitions
        email-service.feature
      data/
        users/
          valid-users.json        ← test fixture data
          invalid-emails.json

Naming conventions:

  • Feature files: kebab-case matching the operation (create-user.feature)
  • Helper features: verb-noun (get-token.feature, create-product.feature)
  • Runner class: *Runner.java suffix for surefire include pattern

karate-config.js: evaluated before every feature. Returns an object whose properties become available as variables in all scenarios. Environment-specific config is the primary use case.

// EXAMPLE

karate-config.js

function fn() {
  // Determine target environment from system property
  var env = karate.env || 'dev';
  karate.log('karate.env =', env);

  var config = {
    env: env,
    baseUrl: 'http://localhost:8080',   // default
    adminToken: 'dev-static-token'
  };

  if (env === 'staging') {
    config.baseUrl = 'https://staging.api.example.com';
    // Fetch dynamic token for staging
    var auth = karate.call('classpath:helpers/get-token.feature');
    config.adminToken = auth.accessToken;
  }

  if (env === 'prod') {
    config.baseUrl = 'https://api.example.com';
    var auth = karate.call('classpath:helpers/get-token.feature');
    config.adminToken = auth.accessToken;
    karate.configure('ssl', true);  // might need relaxed SSL on some envs
  }

  // Increase timeout for slow environments
  karate.configure('connectTimeout', 10000);
  karate.configure('readTimeout', 10000);

  return config;
}

// WHAT INTERVIEWERS LOOK FOR

Domain-based folder organisation (not test-type-based), the helpers/ and mocks/ separation, karate-config.js location and purpose, and the surefire runner naming convention. This structure is standard in real Karate projects.

// COMMON PITFALL

Putting all feature files in a flat directory — this is unmanageable at 50+ features. Domain-based subfolders and a helpers/ separation are essential from the start.