Skip to main content
By default, hitspec executes requests in the order they appear in the file. The @depends directive lets you declare explicit dependencies between requests, ensuring that prerequisite requests run first regardless of file order.

Basic Usage

Add # @depends <requestName> to any request that relies on another:
### Login
# @name login

POST {{baseUrl}}/auth/login
Content-Type: application/json

{"email": "test@example.com", "password": "secret"}

>>>capture
token from body.token
<<<

### Get profile
# @name getProfile
# @depends login

GET {{baseUrl}}/me
Authorization: Bearer {{login.token}}

>>>
expect status 200
<<<
The getProfile request will always execute after login, even if you run tests in parallel mode or filter to a specific request.

Multiple Dependencies

A request can depend on multiple other requests. Separate names with commas:
### Setup database
# @name setupDb

POST {{baseUrl}}/test/seed
Content-Type: application/json

{"fixture": "users"}

>>>
expect status 200
<<<

### Login
# @name login

POST {{baseUrl}}/auth/login
Content-Type: application/json

{"email": "admin@example.com", "password": "secret"}

>>>capture
token from body.token
<<<

### Run protected operation
# @name protectedOp
# @depends setupDb, login

POST {{baseUrl}}/admin/report
Authorization: Bearer {{login.token}}

>>>
expect status 200
<<<
All listed dependencies must complete before the dependent request runs. The dependencies themselves can run in any order (or in parallel, when --parallel is enabled).

How It Works

Topological Sort

hitspec builds a directed acyclic graph (DAG) from the @depends declarations and performs a topological sort to determine execution order. This means:
  • Dependencies always run before the requests that need them
  • Independent requests can run in any order
  • With --parallel, independent requests run concurrently
Given this dependency graph:
login ──────────┐
                ├──> getProfile
setupDb ────────┘
                ├──> createPost ──> verifyPost
login ──────────┘
hitspec determines that login and setupDb can run in parallel, getProfile and createPost must wait for their dependencies, and verifyPost runs last.

Cycle Detection

hitspec detects circular dependencies at parse time and reports an error:
### Request A
# @name a
# @depends b

GET {{baseUrl}}/a

### Request B
# @name b
# @depends a

GET {{baseUrl}}/b
This produces an error:
Error: circular dependency detected: a -> b -> a
Circular dependencies are always a configuration error. Restructure your tests so the dependency chain flows in one direction.

Cross-File Dependencies

Dependencies work across files within the same test run. If login is defined in auth.http and createPost in posts.http, you can still declare:
# In posts.http
### Create a post
# @name createPost
# @depends login

POST {{baseUrl}}/posts
Authorization: Bearer {{login.token}}
Content-Type: application/json

{"title": "Hello"}
As long as both files are included in the test run:
hitspec run auth.http posts.http
# or
hitspec run tests/    # if both files are in tests/

Implicit Dependencies via Captures

Using a captured variable implicitly requires the capturing request to run first, but hitspec does not infer this automatically. You must always declare @depends explicitly:
### Login
# @name login

POST {{baseUrl}}/auth/login
Content-Type: application/json

{"email": "test@example.com", "password": "secret"}

>>>capture
token from body.token
<<<

### Get data (WRONG -- missing @depends)
GET {{baseUrl}}/data
Authorization: Bearer {{login.token}}

### Get data (CORRECT)
# @depends login
GET {{baseUrl}}/data
Authorization: Bearer {{login.token}}
Without @depends, hitspec may execute requests in any order (especially with --parallel), causing captured variable references to resolve to empty strings.

Dependency Chains

Dependencies are transitive. If A depends on B and B depends on C, then A implicitly waits for both B and C:
### Step 1: Create org
# @name createOrg

POST {{baseUrl}}/orgs
Content-Type: application/json

{"name": "Test Org"}

>>>capture
orgId from body.id
<<<

### Step 2: Create team (depends on org)
# @name createTeam
# @depends createOrg

POST {{baseUrl}}/orgs/{{createOrg.orgId}}/teams
Content-Type: application/json

{"name": "Engineering"}

>>>capture
teamId from body.id
<<<

### Step 3: Add member (depends on team, which depends on org)
# @name addMember
# @depends createTeam

POST {{baseUrl}}/teams/{{createTeam.teamId}}/members
Content-Type: application/json

{"userId": "user-123"}

>>>
expect status 201
<<<
You do not need to write # @depends createOrg, createTeam on addMember — depending on createTeam is sufficient because createTeam already depends on createOrg.

Parallel Execution with Dependencies

When you run tests with --parallel, hitspec respects all @depends constraints while maximizing concurrency for independent requests:
hitspec run tests/ --parallel --concurrency 5
In this mode:
  • Requests with no dependencies start immediately
  • Requests with satisfied dependencies start as soon as their prerequisites complete
  • The --concurrency flag limits how many requests run simultaneously

Filtered Execution

When you filter tests by name or tag, hitspec automatically includes any dependency that the filtered request needs:
# Runs "login" automatically because getProfile depends on it
hitspec run tests/ --name getProfile
# Runs any dependencies of smoke-tagged requests
hitspec run tests/ --tags smoke

Common Patterns

Setup and Teardown

### Seed test data
# @name setup
# @tags setup

POST {{baseUrl}}/test/seed

>>>
expect status 200
<<<

>>>capture
testUserId from body.userId
<<<

### Run test
# @name mainTest
# @depends setup

GET {{baseUrl}}/users/{{setup.testUserId}}

>>>
expect status 200
<<<

### Clean up
# @name teardown
# @depends mainTest

DELETE {{baseUrl}}/test/cleanup

>>>
expect status 200
<<<

Fan-Out Pattern

Multiple requests depend on a single setup step:
### Login
# @name login

POST {{baseUrl}}/auth/login
Content-Type: application/json

{"email": "admin@example.com", "password": "secret"}

>>>capture
token from body.token
<<<

### Test users endpoint
# @depends login

GET {{baseUrl}}/users
Authorization: Bearer {{login.token}}

>>>
expect status 200
<<<

### Test posts endpoint
# @depends login

GET {{baseUrl}}/posts
Authorization: Bearer {{login.token}}

>>>
expect status 200
<<<

### Test comments endpoint
# @depends login

GET {{baseUrl}}/comments
Authorization: Bearer {{login.token}}

>>>
expect status 200
<<<
With --parallel, the three test requests run concurrently after login completes.