Project Brief — API Test Suite for a User Management System

10 min read

The previous five chapters built every component of a Karate framework one lesson at a time: project setup, HTTP verbs, assertions, schema validation, variables, file reading, data-driven testing, feature reuse, authentication patterns, retry polling, parallel execution, and CI/CD. The capstone puts them together against a realistic end-to-end scenario — a user management API called TeamHub. You'll build a complete Karate suite, from pom.xml to GitHub Actions, covering CRUD, roles, teams, data-driven cases, schema validation, and parallel execution. By the end you'll have a portfolio-quality project that demonstrates every skill the course covered.

The scenario: TeamHub

TeamHub is a fictional SaaS platform for managing engineering teams. Three roles, three resources, and a business workflow around team membership:

  • Rolesadmin (full access to everything), manager (manage their team's members and permissions), member (view team data, update own profile).
  • Resources — users (name, email, role, status), teams (name, description, ownerId), memberships (userId, teamId, joinedAt).
  • Workflow — an admin creates a team, adds users as members, a manager updates a member's role, a member views their team — and all of this is protected by the role that the Bearer token carries.

That's a small, plausible API. It exercises every Karate feature without becoming a project that takes a week to build.

The endpoints

Imagine the API looks like this:

Auth
  POST   /auth/login                 — returns Bearer token
  POST   /auth/logout                — invalidates token

Users
  GET    /users                      — list (admin/manager)
  POST   /users                      — create user (admin)
  GET    /users/{id}                 — get user (admin/manager/self)
  PUT    /users/{id}                 — full update (admin/manager)
  PATCH  /users/{id}                 — partial update (admin/manager/self)
  DELETE /users/{id}                 — delete (admin)

Teams
  GET    /teams                      — list (admin/manager)
  POST   /teams                      — create (admin)
  GET    /teams/{id}                 — get team (admin/manager/member)
  PUT    /teams/{id}                 — update (admin/manager)
  DELETE /teams/{id}                 — delete (admin)

Memberships
  POST   /teams/{id}/members         — add member (admin/manager)
  DELETE /teams/{id}/members/{userId} — remove member (admin/manager)
  GET    /teams/{id}/members         — list members (admin/manager/member)

There is no live TeamHub server — that's intentional. Stub it with Mockoon, WireMock standalone, or json-server. Alternatively, substitute JSONPlaceholder for the happy-path tests and focus on the framework structure. What matters is what you build, not which server it talks to.

Deliverables

By the end of the project you should be able to point at a Git repository and run mvn clean verify to see everything work end to end.

1. Maven project (pom.xml) One dependency: karate-junit5 at test scope. Java 21 toolchain. The <testResources> block so Maven picks up .feature files from src/test/java.

2. karate-config.js with environment switching Returns baseUrl that switches between dev and staging based on karate.env. Reads credentials from java.lang.System.getenv(). Sets global auth headers via karate.configure('headers', ...) using karate.callSingle() to log in once per suite.

3. Reusable common features

  • common/login.feature — accepts email and password, returns authToken.
  • common/create-user.feature — accepts user fields, POSTs to /users, returns userId.
  • common/create-team.feature — accepts team fields, POSTs to /teams, returns teamId.
  • common/helpers.jsgenerateEmail(prefix), generateName() using java.lang.System.currentTimeMillis().

4. At least 20 scenarios across 5 feature files

Feature fileScenariosWhat it covers
auth/auth.feature4Login success, wrong password → 401, missing token → 401, expired token → 401
users/users.feature6CRUD, list pagination, GET own profile, schema validation
teams/teams.feature4Create, read, update, delete — with role-based access checks
memberships/memberships.feature4Add member, list members, remove member, member views their team
users/users-data-driven.feature3+Scenario Outline from CSV for user creation validation cases

5. Data-driven tests with Scenario Outline + CSV users/test-users.csv with valid and invalid user rows. A Scenario Outline that runs each row and asserts the correct status code — 201 for valid, 400/422 for invalid.

6. Schema validation with Karate markers on all responses schemas/user-schema.json and schemas/team-schema.json using fuzzy markers. Every GET scenario validates the response shape with match response == read('classpath:schemas/user-schema.json').

7. Retry pattern for at least one async operation One scenario that simulates an async operation (e.g., user provisioning) with configure retry and retry until response.status == 'active'. Even a 3-attempt retry against a synchronous stub demonstrates the pattern.

8. Parallel execution runner ParallelRunner.java using Runner.path("classpath:").outputCucumberJson(true).parallel(4). The assertEquals guard fails the Maven build on any scenario failure.

9. GitHub Actions CI pipeline .github/workflows/karate-tests.yml that runs on push/PR, injects environment secrets, runs mvn clean verify, uploads the Karate report with if: always().

10. Reporting Built-in Karate HTML report plus maven-cucumber-reporting plugin generating target/cucumber-html-reports/.

Stretch goals:

  • Karate UI test that logs into a frontend and verifies a user appears after API creation
  • Allure integration with trend tracking across runs
  • common/wait-for-status.feature as a reusable polling helper
  • Gatling simulation reusing users.feature for a basic load test

How the deliverables map to the course chapters

TeamHub test suite
  • – Maven project + runner
  • – karate-config.js
  • – CRUD feature files
  • – match assertions + schema
  • – def + embedded expressions
  • – read() for JSON/CSV files
  • – Scenario Outline + CSV
  • – call / callonce login
  • – Global auth in karate-config.js
  • – retry until for async
  • – parallel(4) runner
  • – Karate UI smoke check
  • Built-in HTML report –
  • outputCucumberJson(true) –
  • maven-cucumber-reporting –
  • GitHub Actions + artefacts –

Suggested project structure

teamhub-karate/
├── pom.xml
├── .github/workflows/karate-tests.yml
└── src/test/java/
    ├── karate-config.js
    ├── ParallelRunner.java
    ├── common/
    │   ├── login.feature
    │   ├── create-user.feature
    │   ├── create-team.feature
    │   └── helpers.js
    ├── schemas/
    │   ├── user-schema.json
    │   └── team-schema.json
    ├── auth/
    │   └── auth.feature
    ├── users/
    │   ├── users.feature
    │   ├── users-data-driven.feature
    │   └── test-users.csv
    ├── teams/
    │   └── teams.feature
    └── memberships/
        └── memberships.feature

Eight directories, each with a single concern. The runner at the root finds everything via classpath:.

Suggested order of work

A reasonable sequence over 5–8 sessions:

  1. Scaffold the Maven project and karate-config.js. Point at JSONPlaceholder or your stub. Write one trivial GET scenario that asserts 200. Commit and confirm CI runs it.
  2. Authentication. Build common/login.feature. Wire callonce into at least one feature file's Background. Write the four auth scenarios (valid login, wrong password, missing token, expired token).
  3. Users CRUD. Write all six user scenarios using call common/create-user.feature for setup. Add schema validation for GET responses.
  4. Teams and memberships. Repeat the CRUD pattern. Write the add-member/remove-member/list-members scenarios. Assert the membership list changes correctly.
  5. Data-driven. Create test-users.csv and write the Scenario Outline. Include at least three valid rows and two invalid rows.
  6. Parallel runner and CI. Replace the per-feature runners with ParallelRunner.java. Add the GitHub Actions workflow. Push and confirm the CI job passes.
  7. Reporting. Add .outputCucumberJson(true) and the Masterthought plugin. Run mvn verify. Share the report link.
  8. Polish and stretch. Add retry to one scenario, add a Karate UI smoke check, or wire Allure.

Each step is one focused session. The full project is a comfortable week of evening work.

⚠️ Common mistakes

  • Building all the helpers before the first test runs. Scaffold everything up front and you'll spend hours writing code that doesn't work yet. Instead: write one test, make it green, extract the helper only when a second test needs the same logic. The capstone framework should emerge from the tests, not precede them.
  • No cleanup between tests. Scenarios that create users without deleting them pollute the stub or database by hundreds of rows across multiple runs. Write teardown calls (method delete) at the end of creation scenarios, or use karate.callSingle() to create shared test data once and reuse it instead of creating fresh data per scenario.
  • Skipping the negative test cases. The most realistic part of this capstone is the auth matrix: does a member token correctly get a 403 on an admin-only endpoint? Does a missing token get a 401? These cases take five minutes to write and are the most commonly skipped in real projects. Write them first.

🎯 Practice task

This is the project. Your practice is to build it across 5–8 focused sessions.

  1. Today (45 min): scaffold the Maven project. Add karate-junit5, the <testResources> block, and a minimal karate-config.js pointing at JSONPlaceholder or your stub. Write one GET scenario. Run it green. Push to a new GitHub repository.
  2. Session 2 (90 min): build common/login.feature (real or simulated) and wire callonce into auth/auth.feature. Write the four auth scenarios.
  3. Session 3 (90 min): write all six user scenarios. Add schemas/user-schema.json and validate GET responses with match response == read(...).
  4. Session 4 (90 min): write teams and memberships. Use call common/create-team.feature for setup data. Write at least one scenario per membership operation.
  5. Session 5 (60 min): write the Scenario Outline with CSV. Add ParallelRunner.java. Add the GitHub Actions workflow.
  6. Session 6 (45 min): add outputCucumberJson(true), the Masterthought plugin, and mvn verify. Confirm both report types generate.
  7. Session 7 (optional stretch): add retry to one scenario, add a Karate UI smoke check, or integrate Allure.

The next lesson is the guided walkthrough — read it when you're stuck on a specific component, or after you've finished as a sanity check against the reference implementation.

// tip to track lessons you complete and pick up where you left off across devices.