Skip to content

Soft assertions

In tryke, assertions are soft by default. Every assertion in a test runs even if earlier ones fail. This is the opposite of pytest, where the first failing assert stops the test.

Why soft assertions

With hard assertions, you fix one failure at a time:

# pytest — only sees the first failure per run
def test_response():
    assert response.status == 200   # fails, test stops here
    assert "ok" in response.body    # never runs
    assert "json" in response.type  # never runs

With soft assertions, you see everything that's wrong in a single run:

from tryke import expect, test

@test
def response_check():
    expect(response.status).to_equal(200)     # fails, continues
    expect(response.body).to_contain("ok")    # runs, may also fail
    expect(response.type).to_contain("json")  # runs, may also fail

This is especially valuable when tests are slow (network calls, database setup) or when failures tend to cluster.

Per-assertion diagnostics

Each soft assertion produces its own diagnostic output showing the expected and actual values. When multiple assertions fail, you see all of them in the test report — not just the first one.

.fatal() for early stopping

Sometimes continuing after a failure doesn't make sense. Chain .fatal() to stop the test immediately:

@test
def check_response():
    expect(response.status).to_equal(200).fatal()  # stop if wrong status
    expect(response.body).to_contain("ok")          # only runs if status was 200
    expect(response.headers).to_contain("json")     # only runs if status was 200

Use .fatal() when later assertions depend on an earlier one passing — like checking a status code before inspecting the body.

Comparison with pytest

Behavior pytest tryke
Default Hard — first failure stops the test Soft — all assertions run
Early stop Default behavior Opt-in via .fatal()
Diagnostic output One failure per test per run All failures per test per run