When a Test Fails¶
A Stove test failure still has a stack trace, but the useful context is the evidence around it: console report, dashboard timeline, span tree, and optional MCP queries. Scroll to walk through what happens when a test goes red.
1. Assertion fails
You wrote a normal Stove test. shouldBePublished times out. The expected Kafka event never showed up.
The assertion failure anchors the report. Dashboard, tracing, and MCP add more evidence when enabled.
// OrderE2ETest.kt test("order is published after POST /orders") { stove { http { post<OrderResponse>("/orders", ...) } kafka { shouldBePublished<OrderCreated> { actual.userId == userId } } } } FAILED after 10.0s org.opentest4j.AssertionFailedError: No matching OrderCreated event arrived within 10s on topic order.created.v1.
2. Console report fills in context
Stove's reporter prints the timeline that led up to the assertion: every HTTP call, every DB row, every published event, every WireMock stub hit. All serialized side-by-side with the failure.
No more guessing whether the bug was in your test, the app, or a downstream mock.
─── Stove Report ───────────────────────────────── ▶ http POST /orders 201 42ms ▶ postgres INSERT INTO orders 1 row 6ms ▶ wiremock GET /inventory/x-1 200 3ms ✘ kafka shouldBePublished<OrderCreated> topic=order.created.v1 timeout=10s seen on bus: (none) most recent topics: order.failed.v1 (1) ────────────────────────────────────────────────────
3. Dashboard renders the full timeline
If the local dashboard is running, the same execution shows up as a clickable timeline at http://localhost:4040. System snapshots, message payloads, DB rows, all queryable.
Drill into the Kafka panel: the app published to order.failed.v1, not order.created.v1. Bug found.
┌─ Timeline ─────────────────────────────────────┐ │ 00:00.012 http POST /orders 201 │ │ 00:00.054 postgres INSERT orders 1 │ │ 00:00.061 wiremock GET /inventory/x-1 200 │ │ 00:00.080 kafka published !? │ │ └─ topic: order.failed.v1 │ │ payload: {reason:"stock=0"} │ │ 00:10.001 assertion timeout │ └────────────────────────────────────────────────┘
4. Trace tree shows the call chain inside the app
When tracing is enabled and the AUT is instrumented, the trace tree shows where the decision was made: controller, service, Kafka producer, and timing on each hop.
▾ POST /orders 42ms ├─ OrderController.create 2ms ├─ ▾ OrderService.place 35ms │ ├─ InventoryClient.fetch 7ms │ ├─ ▾ StockGuard.check 1ms │ │ └─ returned: INSUFFICIENT │ └─ KafkaProducer.send 3ms │ topic = order.failed.v1 └─ HTTP 201 returned
5. AI agent triages via MCP
The same data is exposed over a loopback MCP endpoint. An agent (Claude Code, Cursor, etc.) can fetch failures and traces directly. No shell-out, no log scraping, no token waste on noisy stdout.
It can return a focused diagnosis when the stored evidence is sufficient.
$ curl localhost:4040/mcp/tools/stove_failure_detail \
-d '{"test_id":"OrderE2ETest#order-publish"}'
{
failure: "kafka.shouldBePublished timeout",
expected_topic: "order.created.v1",
observed_topics: ["order.failed.v1"],
span: "StockGuard.check returned INSUFFICIENT",
suggestion: "InventoryClient returns stock=0. Verify
test fixture seeded inventory before order"
}
How to get this loop in your project¶
This experience requires three things, all opt-in:
-
Tracing
OpenTelemetry receiver plus JVM agent attachment for in-process JVM apps; non-JVM apps use their language SDK.
-
Dashboard
Local SQLite-backed UI streaming live test runs.
-
MCP
Loopback agent endpoint exposed by
stove-cli.