Integration tests that use your app the way your users do.

Recorded from real traffic. Run on every pull request.

2,189 unit tests. One flow. Eight bugs.

The unit tests caught 5. The flow caught 6. Each caught a bug the other missed, and one got past both.

One named experiment on a small shop app, not a product benchmark. Read the method and every row.

Caught byUnitFlow

4Both

  • Body parser moved below the routes
  • Route renamed
  • Login and auth read different secrets
  • New required column

2Only the flow

  • Login token renamed, unit tests updated with it
  • Create answers 200 instead of 201

1Only the unit tests

  • A product update with no tags wipes the tags

1Neither

  • A field renamed to camelCase in the product list
Total5/86/8

Keep your unit tests.

Unit tests

They check the logic inside one function and point at the line that broke. They can't see how the parts connect.

An API flow

It calls your running app like a client: routes, login, database. It catches the bugs between the parts, and only fails on what it checks.

Three commands to a check on every PR.

  1. 1Record

    Use your app on localhost. Each journey becomes a YAML flow in api-tests/.

    $ npx stresseur record

    $ npx stresseur generate

  2. 2Add to CI

    Writes the GitHub Actions workflow that runs your flows on every pull request.

    $ npx stresseur init-ci

  3. 3Check every PR

    One check and one comment per pull request, updated on each push.

    Stresseurcheck

What a flow checks.

Real routes
Every request goes through your router and middleware, in the order your app sets them.
Real auth
The flow logs in like a client and sends the token it got back.
The database
Creates, reads and updates hit your real schema, columns and constraints.
Values between steps
A token or an ID from one response feeds the next request, mapped from the recording.
api-tests/shop.yamlflow.yamlexcerpt
- request:    name: Login    method: POST    url: '{{ #env:APP_URL }}/api/auth/login'- request:    name: ListCategories    depends_on: Login    method: GET    url: '{{ #env:APP_URL }}/api/categories'    headers: { Authorization: 'Bearer {{ Login.response.body.token }}' }    assertions:      - response.status == 200

If login stops returning token, the next step gets a 401 and the check fails.

Add the test your unit suite can't write.

The free plan covers 1 private repo.