skip to content

Adoption and Wiring

How a suite of feature files meets the world outside it: the Java class that starts a run, and the case for picking this tool at all. Interviewers use it to test adoption judgement.

on this pageshow

explore

questions

11

Karate and a Java API-testing library such as REST Assured both drive HTTP calls and assert on responses. What is written differently in a Karate project, and what does that remove?

level: juniorimportance: must knowfreq 72%

answer

  1. Ask where a step's implementation lives
  2. One artefact, not two
  3. No step-definition layer between text and call
  4. Keywords are Karate's own and fixed
  5. Body and assertion inline: request, match

basics

~20 s

In Karate the test is a .feature file whose steps are the framework's own keywords, so there is no step-definition layer to write: the HTTP call, the request payload and the assertion all live in that one file.

solid answer

~50 s

A Karate test **is** a `.feature` file. Its steps — `url`, `path`, `request`, `method`, `status`, `match` — are keywords Karate itself resolves, so nothing binds a line of text to a method you wrote: there is no step-definition layer and no package of step definitions for a runner to find. A JSON body is written inline as a literal (`And request { name: 'Fluffy', age: 3 }`) and the assertion is a built-in step (`Then match response contains { name: 'Fluffy' }`) rather than a matcher chain you compose in Java. REST Assured is the opposite arrangement — the test is Java source calling a library — and a Cucumber-style suite keeps the feature file but still needs a Java method behind every line. Karate removes that middle layer; what it costs is that your test is no longer Java source.

code

gherkin · 16 lines
gherkin
Feature: cats

  Background:
    * url baseUrl

  Scenario: create and read a cat
    Given path 'cats'
    And request { name: 'Fluffy', age: 3 }
    When method post
    Then status 201
    * def catId = response.id

    Given path 'cats', catId
    When method get
    Then status 200
    And match response contains { name: 'Fluffy', age: 3 }

go deeper

for a junior

Remember the shape: one .feature file carries the URL, the request body and the assertion, and no Java class sits behind any line of it.

for a middle

Be able to say why nothing binds text to code. The keyword set is Karate's own and fixed, so a step is either a keyword or a JavaScript expression.

for a senior

Name the cost as fluently as the benefit: the compiler stops checking your steps, so a renamed field or a typo surfaces only when the scenario runs.

for a principal

Frame it as where the team wants its centre of gravity - one readable artefact under normal code review, against the JVM tooling a Java suite keeps.

## The three arrangements Three tools can drive the same HTTP call and assert on the same response. They differ in one structural place: where the **implementation** of a step lives. | Tool | Where the test lives | What binds a line to the HTTP call | What a new step costs you | |---|---|---|---| | Karate | a `.feature` file | one of Karate's own keywords | nothing — you reuse a keyword | | REST Assured | Java source | you call the library directly | a Java method | | Cucumber over a Java API library | a `.feature` file **and** Java source | a step definition you author | a sentence **and** a Java method | Karate is the only one of the three where the feature file is the complete artefact, and that is the claim the whole trade-off turns on. ## Why there is nothing to bind Karate reads feature files with its own lexer and parser, not with Cucumber's Gherkin library, and it has no step-definition registry at all. Its step vocabulary comes out of Karate's own source and is fixed: `url`, `path`, `param`, `header`, `request`, `method`, `status`, `match`, `assert`, `def`, `json`, `xml`, `call`, `callonce`, `configure`, `retry until` and a few dozen more. There is no service loader for step keywords, no annotation you can put on a class of your own, and no directory the runner scans for your code. A step is therefore one of exactly two things: a keyword Karate knows, or a JavaScript expression. The practical effect is that a Karate project has **one** kind of artefact where a Cucumber-style project has two, and where a REST Assured project has Java classes that the non-Java people on the team will never open. ## What the removal buys - **No sentence-to-method mapping to keep in sync.** A step is not a sentence somebody still has to implement; it *is* the implementation. - **Payloads as literals.** `And request { name: 'Fluffy', age: 3 }` is the body. Keys need no quoting, and the same shape is reused on the expected side of a `match`. - **Assertion in the language.** `match` is a step, not a matcher library you compose calls into. It compares whole JSON and XML documents, so the common case — "does this response look like this?" — is one line. - **One file to read in review.** Scenario, data and expectation are on the screen together. - **A file a non-Java reader can follow.** Not a specification the business writes, but a test a product person or a manual tester can read and often edit. ## What it does not remove Two things people expect to disappear and do not: 1. **You still have a JVM project.** Karate runs on the JVM, is built with Maven or Gradle, and its launcher and reports are Java. The "no code" impression is wrong. 2. **You still write logic.** Anything the keyword set does not cover — a signature, a date calculation, a loop over accounts — goes into JavaScript in the feature file, or into a Java class reached with `Java.type('com.example.util.Signer')`. And the cost is real. Once the test stops being Java source: - the compiler no longer checks the field names, variable names or method names in your steps; - an IDE cannot rename a variable across feature files the way it renames a Java field; - the expressions in your steps run on Karate's JavaScript engine, not under the JVM's type system; - a helper you would have written as a typed class is now a JavaScript function unless you deliberately push it back into Java. ## Where a saved collection sits in this picture A Postman collection is a third model again: the request set is a document authored in a GUI and exported as JSON, rather than source you write and review in the repository. That is not a criticism, it is a different centre of gravity, and it matters here because the argument for Karate is usually made against it. A `.feature` file is hand-written text that diffs and reviews like the rest of the codebase, so it falls under the same branch, review and CI rules as the service it tests. A team happy with a GUI-authored request set and a headless run in CI is not the team Karate's model is aimed at. ## How to answer this in an interview Lead with the structural difference: the feature file is the test, and no step-definition layer sits between the text and the HTTP call, because the keywords are Karate's own and fixed. Give one concrete pair — `And request { ... }` for the body, `Then match response contains { ... }` for the assertion — to show you have written one. Then name the cost in the same breath: everything the compiler used to check is now text that fails when the scenario runs. This is asked as a tool-choice question, and the answer that lands is the one that argues both sides.

  • Does Karate depend on Cucumber?
    No. Karate parses feature files with its own lexer and parser and carries no step-definition registry — there is no `io.cucumber` dependency anywhere in the project. It can still write a Cucumber-JSON report file, which is a report format other tools consume, not a runtime dependency.
  • If the keyword set is fixed, how do you do something Karate has no keyword for?
    Write it as JavaScript in the feature file, put it in a `.js` file the feature reads, or reach an existing Java class with `Java.type('com.example.util.Signer')`. There is no way to add a keyword — the vocabulary belongs to Karate.
  • What in a Karate project is still ordinary Java?
    The launcher class that starts the suite, any helper classes you reach with `Java.type`, and the build file. Karate is a JVM library: the feature files are the tests, but the project around them is a normal Maven or Gradle project.

saying these in an interview costs you the question

  • Says Karate runs on Cucumber or needs it on the classpath
  • Claims Karate is codeless; it is a JVM project with JavaScript in its steps
  • Cannot name one Karate keyword, only the Gherkin-looking shape
  • Says you register your own keywords to extend Karate's vocabulary
  • Argues only the upside and names no cost for leaving Java source
open as a page

In Karate, what does the Java line `Runner.path("classpath:animals").tags("@smoke").parallel(5)` actually do, and why does this class need no step-definition or glue package?

level: juniorimportance: must knowfreq 76%

basics

~20 s

Runner.path() opens Karate's builder, each chained call sets one option, and parallel(n) is the terminal call that discovers the features, runs them on n threads and returns a result object. No glue package is involved.

open as a page

A team moves its API suite from a Java library like REST Assured onto Karate feature files. Which compile-time guarantees does that give up, and what does Karate offer in their place?

level: middleimportance: must knowfreq 58%

basics

~10 s

Every compile-time guarantee goes: a Karate step is text and its expressions are JavaScript, so variable, field and method names are unchecked until the scenario runs. Karate replaces them with runtime failure and Java.type.

open as a page

In a Karate Java runner, what does `Runner.path("classpath:api").tags("@smoke,@sanity", "~@wip")` select, and how do the comma, the tilde and the two separate arguments each combine?

level: middleimportance: must knowfreq 68%

basics

~10 s

That chain runs scenarios tagged @smoke or @sanity but not @wip. Separate arguments are ANDed, a comma inside one argument means OR, and a leading tilde negates that whole argument.

open as a page

In Karate's JUnit integration, what is the `@Karate.Test` annotation, where may it be placed, and what must the annotated method return?

level: juniorimportance: should knowfreq 42%

basics

~10 s

Karate's @Karate.Test is a method-level annotation meta-annotated with JUnit's @TestFactory. The method must return a Karate instance, an Iterable of dynamic nodes, so each feature and scenario becomes its own test.

open as a page

Karate's step keyword set is fixed and there is no way to register a new one. In a Karate feature file, how do you run logic Karate has no keyword for, and what does `Java.type('com.example.util.Signer')` give you?

level: middleimportance: should knowfreq 46%

basics

~20 s

Write it as JavaScript in the feature file, or reach a Java class with Java.type('com.example.util.Signer'), which loads that class and returns it so its static methods and its constructor are callable from a step. JSON arrives there as plain Map and List.

open as a page

A Karate runner calls `Runner.path("classpath:api").tags("~@ignore").parallel(4)`. Does the `~@ignore` do anything, and can any tag expression make an `@ignore`d Scenario run?

level: middleimportance: should knowfreq 47%

basics

~20 s

Karate skips an @ignore scenario before the tag selector is evaluated, so ~@ignore is redundant, and no tag expression can select one back in. Only a line filter, a scenario-name filter or a call reaches it.

open as a page

A suite launched with `Runner.path("classpath:api").parallel(4)` writes an HTML report, but the CI job reports "no tests found" because it can find no XML. Which Karate builder defaults explain that, and where does Karate write its output?

level: middleimportance: should knowfreq 52%

basics

~20 s

Karate's HTML report is on by default but JUnit XML and Cucumber JSON are off; you must call outputJunitXml(true). Output goes to karate-reports under the build directory, not to the surefire directory CI usually reads.

open as a page

Karate covers API tests, a mock server and a Gatling load bridge in one tool. What does driving a load run from the same `.feature` file buy, and where does that one-tool model stop paying?

level: seniorimportance: should knowfreq 40%

basics

~20 s

One artefact: karate-gatling points a simulation at a .feature file, so the functional scenario and its assertions become the load script. It stops paying because Karate builds an HTTP client per scenario, which under load opens a connection per iteration.

open as a page

A Karate runner class hard-codes `Runner.path("classpath:api").tags("@regression").karateEnv("dev").parallel(4)`. How do you get one CI job to run only `@smoke` against `qa` on eight threads without editing that class?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Pass the karate.options system property, for example -Dkarate.options="--tags @smoke --env qa --threads 8". Karate reads it inside parallel() and overrides the builder's values, so the compiled class stays untouched.

open as a page

Your team has a REST Assured suite and a set of Postman collections. How would you decide whether to consolidate API testing on Karate, and what would make you refuse?

level: principalimportance: should knowfreq 36%

basics

~20 s

Decide on who maintains the suite and what it gives up, not on syntax. Karate wins when one readable artefact under normal code review beats Java tooling; refuse when the suite's value is typed helpers the compiler protects.

open as a page