Migrating from pytest + httpx to the Mockarty Tester
pytest + httpx is the canonical Python HTTP test stack. The Mockarty
Tester DSL is a drop-in replacement when you want:
- Multi-protocol reach in one DSL (HTTP, gRPC, GraphQL, Kafka,
RabbitMQ, SSE, WebSocket, SOAP, DB) - Variable interpolation across chain steps with
{{token}}syntax - TCM external-run upload in one call
At a glance
| pytest + httpx | Mockarty Tester (Python) |
|---|---|
httpx.get(url) |
t.http().get(url) |
resp.status_code == 200 |
.expect_status(200) |
assert resp.json()["name"] == "Alice" |
.expect_json_path("$.name", "Alice") |
assert "abc" in resp.text |
.expect_body_contains("abc") |
resp.headers["X-Foo"] == "y" |
.expect_header("X-Foo", "y") |
httpx.post(url, json={...}) |
.post(url).json({...}) |
httpx.Client(headers={...}) |
Tester(default_headers={...}) |
Reusing token = resp.json()["token"] |
.extract("$.token", "token") |
Then headers={"Authorization": f"Bearer {token}"} |
.header("Authorization", "Bearer {{token}}") |
| Parametrize via fixture | Pre-populate via t.set_var(...) |
Side-by-side example
pytest + httpx
import httpx
import pytest
def test_login_and_me():
base = "http://localhost:8080"
with httpx.Client(base_url=base) as c:
login = c.post("/login", json={"user": "alice"})
assert login.status_code == 200
token = login.json()["token"]
me = c.get("/me", headers={"Authorization": f"Bearer {token}"})
assert me.status_code == 200
assert me.json()["user"] == "alice"
Mockarty Tester
from mockarty.tester import Tester
def test_login_and_me():
with Tester(base_url="http://localhost:8080") as t:
(t.http().post("/login")
.json({"user": "alice"})
.expect_status(200)
.extract("$.token", "token"))
(t.http().get("/me")
.header("Authorization", "Bearer {{token}}")
.expect_status(200)
.expect_json_path("$.user", "alice"))
assert t.ok(), t.errors()
Why migrate
- Vocabulary stays the same across Go / Python / Java. A QA team
writing Tester chains in Python can hand the source to a Go-shop
to maintain — the chain reads identically. - Allure / TCM out of the box. The Tester captures every step
with timing + status + protocol metadata.to_report_kwargs(t, ...)
maps the result toclient.external_runs.report(**)for TCM upload. - No HTTP boilerplate for chaining. Tester’s
{{var}}template
handles cross-step plumbing without f-string concatenation.
Reporting back to Mockarty TCM
from mockarty import MockartyClient
from mockarty.tester import Tester, to_report_kwargs
with MockartyClient(base_url="http://...", api_key="...", namespace="qa") as client:
with Tester(base_url="http://localhost:8080") as t:
# ... chain
client.external_runs.report(
**to_report_kwargs(t, case_name="Login flow", auto_create=True),
)
The pytest test → IR → TCM external run pipeline closes the loop:
run any pytest, ship the result via the SDK, see it on the
Mockarty admin page next to native test-plan runs.
Coexistence with pytest
The Tester is NOT a pytest replacement — it’s a fluent API for
writing the HTTP / RPC / message-bus pieces of your test. Keep
@pytest.fixture, pytest -k, pytest-xdist etc. — they all work
unchanged. Tester replaces only the httpx-shaped assertions inside
the test body.
import pytest
from mockarty.tester import Tester
@pytest.fixture
def t():
with Tester(base_url="http://localhost:8080") as t:
yield t
@pytest.mark.parametrize("user_id", [1, 2, 3])
def test_user_visible(t, user_id):
t.http().get(f"/users/{user_id}").expect_status(200)
assert t.ok(), t.errors()