Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ellomas.com/llms.txt

Use this file to discover all available pages before exploring further.

Best Practices

Organise Workflows by Domain

Group related workflows in a directory structure:
tests/
├── auth/
│   ├── login.yaml
│   ├── registration.yaml
│   └── password-reset.yaml
├── api/
│   ├── crud-users.yaml
│   └── pagination.yaml
└── db/
    ├── seed.yaml
    └── migrations.yaml
Run all tests in parallel:
replay run tests/**/*.yaml --concurrency 4

Use Config Profiles for Environments

Never hard-code environment URLs or credentials:
# replay.yaml
profiles:
  dev:
    config:
      http:
        base_url: http://localhost:3000
      postgres:
        dsn: postgres://dev:pass@localhost:5433/devdb
  staging:
    config:
      http:
        base_url: https://staging.example.com
      postgres:
        dsn: postgres://deploy:pass@staging-db:5432/stagingdb
replay run tests/ --profile staging

Extract Early, Assert Often

Extract values as soon as they become available and assert at every meaningful checkpoint:
- name: login
  type: http
  request:
    method: POST
    url: /auth/login
  extract:
    token: $.data.token
  assert:
    - ["$.status", "eq", 200]
    - ["$.data.token", "not_null"]

- name: get-profile
  type: http
  request:
    method: GET
    url: /profile
    headers:
      Authorization: Bearer {{ token }}
  assert:
    - ["$.data.email", "not_null"]
    - ["$.data.verified", "eq", true]
This makes failures easy to pinpoint — you know exactly which step broke.

Keep Steps Focused

Each step should do one thing well. Avoid steps with multiple responsibilities:
# Good
- name: create-user
  type: http
  request:
    method: POST
    url: /users
    body:
      email: test@example.com

- name: verify-user-in-db
  type: db
  query: "SELECT id FROM users WHERE email = 'test@example.com'"
  assert:
    - ["$[0].id", "not_null"]

# Bad — mixing concerns in one step
- name: create-and-verify
  type: http
  request:
    method: POST
    url: /users
    body:
      email: test@example.com

Use Deterministic Data

Avoid random values that make tests flaky. When you need unique data, use {{ nowUnix }} or a counter:
- name: create-user
  type: http
  request:
    method: POST
    url: /users
    body:
      email: "qa-{{ nowUnix }}@example.com"

Use ignore_error Sparingly

ignore_error is useful for cleanup steps or optional checks, but overusing it hides real failures:
# Good — cleanup that should not fail the pipeline
- name: cleanup
  type: shell
  command: "rm -rf /tmp/test-data"
  ignore_error: true

# Avoid — this hides a real test failure
- name: critical-check
  type: http
  request:
    method: GET
    url: /health
  assert:
    - ["$.status", "eq", 200]
  ignore_error: true  # ← hides failures!

Template Sensitive Data

Use variables for secrets and credentials:
- name: login
  type: http
  request:
    method: POST
    url: /auth/login
    body:
      email: "{{ API_USERNAME }}"
      password: "{{ API_PASSWORD }}"
Pass them via environment variables or the config file — never hard-code them in workflow files.

Clean Up Test Data

When your workflow creates data, clean it up afterward:
- name: create-test-data
  type: http
  request:
    method: POST
    url: /users
  extract:
    test_user_id: $.data.id

# ... test logic ...

- name: delete-test-data
  type: http
  request:
    method: DELETE
    url: /users/{{ test_user_id }}
  ignore_error: true

Use call for Reusable Steps

Extract common patterns (auth, setup, teardown) into reusable files:
# auth.yaml
name: login
steps:
  - name: login
    type: http
    request:
      method: POST
      url: /auth/login
      body:
        email: "{{ email }}"
        password: "{{ password }}"
    extract:
      token: $.data.token
    returns: [token]
# test.yaml
steps:
  - name: authenticate
    type: call
    file: auth.yaml
    with:
      email: admin@example.com
      password: "{{ ADMIN_PASSWORD }}"
    returns: [token]

Version Your Workflows with the Schema

Add the JSON schema reference to get IDE autocomplete:
# yaml-language-server: $schema=https://raw.githubusercontent.com/tomiwa-a/replay/main/schema.json

Run Workflows in CI with --fail-fast

In CI, --fail-fast saves time by stopping at the first failure:
replay run tests/ --concurrency 4 --fail-fast

What’s Next?