0.24.0¶
Released: May 2026
This release makes Stove a polyglot end-to-end testing framework and rounds out the black-box story. Go applications are now first-class citizens — runnable as host processes or Docker containers, with Kafka, OpenTelemetry, and code coverage support out of the box. stove-container works for any image, regardless of language. providedApplication() unlocks smoke-testing already-deployed apps. Multiple instances of the same system type can now be registered with typed keys for cross-service verification. And the stove CLI gains an MCP server so AI agents can triage failed runs through structured tools instead of raw logs.
New Features¶
providedApplication() — black-box smoke testing against deployed apps¶
Stove no longer requires it to start the application. providedApplication() replaces the framework starter and points Stove at a remote, already-deployed app — staging, pre-prod, or any environment where the artifact is running independently.
Stove().with {
httpClient {
HttpClientSystemOptions(baseUrl = "https://staging.myapp.com")
}
postgresql {
PostgresqlOptions.provided(
jdbcUrl = "jdbc:postgresql://staging-db:5432/myapp",
host = "staging-db", port = 5432,
configureExposedConfiguration = { emptyList() }
)
}
kafka {
KafkaSystemOptions.provided(
bootstrapServers = "staging-kafka:9092",
configureExposedConfiguration = { emptyList() }
)
}
providedApplication {
ProvidedApplicationOptions(
readiness = ReadinessStrategy.HttpGet(
url = "https://staging.myapp.com/health"
)
)
}
}.run()
Includes:
- Optional readiness check (
ReadinessStrategy.HttpGet/TcpPort/Probe/FixedDelay) — Stove waits for the deployed app before running tests - Works with any language or framework — JVM or otherwise
*.provided(...)factory methods on systems (PostgreSQL, MySQL, MSSQL, Cassandra, MongoDB, Redis, Elasticsearch, Couchbase, Kafka, …) point Stove at an existing instance instead of a Testcontainercleanuplambdas on system options for managing test data on shared external infrastructure- No
Bridge/using<T> {}(no local DI container) — by design
Use case: same Stove tests that drive your local Testcontainers-backed e2e suite can run as post-deployment smoke checks against staging — no new framework, no new DSL.
See Provided Application.
Multiple instances of the same system (keyed systems)¶
Stove now supports registering multiple instances of the same system type, each identified by a typed key (SystemKey). Pass the key to both registration and validation DSLs.
object OrderService : SystemKey
object PaymentService : SystemKey
object AppDb : SystemKey
object AnalyticsDb : SystemKey
Stove().with {
httpClient { HttpClientSystemOptions(baseUrl = "https://myapp.com") } // default
httpClient(OrderService) { HttpClientSystemOptions(baseUrl = "https://order.internal") } // keyed
httpClient(PaymentService) { HttpClientSystemOptions(baseUrl = "https://pay.internal") } // keyed
postgresql(AppDb) { /* ... */ }
postgresql(AnalyticsDb) { /* ... */ }
providedApplication()
}.run()
test("create order, verify across services and databases") {
stove {
http { /* default — your app */ }
http(OrderService) { /* downstream order service */ }
http(PaymentService) { /* downstream payment service */ }
postgresql(AppDb) { /* app's database */ }
postgresql(AnalyticsDb) { /* analytics database */ }
}
}
Supported across PostgreSQL, MySQL, MSSQL, MongoDB, Cassandra, Couchbase, Redis, Elasticsearch, HTTP, gRPC, Kafka, WireMock, gRPC Mock. Single-instance systems (Bridge, Tracing, Dashboard) and framework starters do not support keys — there is only one application under test.
Default and keyed instances of the same type coexist independently. Keyed systems get distinguishable names in dashboard reports and traces (HTTP [OrderService] > GET /api/orders/123).
Pairs naturally with providedApplication() for full black-box microservice integration testing across many services and shared databases.
See Multiple Systems.
stove-process — non-JVM applications as host processes¶
New stove-process module starts any binary as the application under test. Works for any language; ships with a goApp() convenience for Go.
Stove().with {
httpClient { HttpClientSystemOptions(baseUrl = "http://localhost:8090") }
postgresql { PostgresqlOptions(...) }
goApp(
target = ProcessTarget.Server(port = 8090, portEnvVar = "APP_PORT"),
envProvider = envMapper {
"database.host" to "DB_HOST"
"database.port" to "DB_PORT"
env("OTEL_EXPORTER_OTLP_ENDPOINT", "localhost:4317")
}
)
}.run()
For other languages, use processApp { ProcessApplicationOptions(...) } with an explicit command.
Includes:
ProcessTarget.Server/ProcessTarget.Workerfor HTTP servers vs. background workersReadinessStrategy.HttpGet/TcpPort/Probe/FixedDelayenvMapperandargsMapperDSLs to map Stove configs to env vars or CLI flags- Graceful shutdown via SIGTERM with configurable timeout
- Background stdout/stderr forwarding
See Go Process Mode and Other Languages & Stacks.
stove-container — applications as Docker images¶
New stove-container module runs the AUT as a Docker image. Language-agnostic — Go, Python, Node.js, Rust, .NET, JVM, anything that ships in a container. Stove only needs an image tag; building the image is your pipeline's job, not Stove's. Use whatever your CI already produces, pull from a registry, or wire an optional local Gradle build task — all three work.
Stove().with {
httpClient { HttpClientSystemOptions(baseUrl = "http://localhost:8090") }
postgresql { PostgresqlOptions(...) }
containerApp(
image = System.getProperty("app.container.image"), // tag from CI / registry / local build
target = ContainerTarget.Server(
hostPort = 8090,
internalPort = 8090,
portEnvVar = "APP_PORT",
bindHostPort = false
),
envProvider = envMapper {
"database.host" to "DB_HOST"
"database.port" to "DB_PORT"
},
configureContainer = {
withNetworkMode("host")
}
)
}.run()
Includes:
- Same
envMapper/argsMappermodel asstove-process ContainerTarget.Server(port-binding or host-network) andContainerTarget.WorkerconfigureContainer { ... }block for TestcontainersGenericContaineraccess (volume mounts, network mode, capabilities, etc.)beforeStarted { ... }hook for pre-start setup with resolved configuration- Graceful container stop with fallback force-close
- Pluggable image registry (
registry,compatibleSubstitute)
In CI, point at the image tag your build pipeline already produced (-Papp.image=... or env var). For local iteration, optionally wire a Gradle Exec task that runs docker build. See Go Container Mode for the full walkthrough.
Go is a first-class citizen¶
The Go showcase recipe (recipes/process/golang/go-showcase) demonstrates an HTTP + PostgreSQL + Kafka service with full tracing, dashboard, and coverage. The same StoveConfig switches between process and container mode via -Dgo.aut.mode=process|container.
Highlights:
- HTTP and database queries traced via
otelhttp+otelsql - W3C
traceparentpropagation correlates Go spans with the originating Stove test go build -coverintegration coverage withGOCOVERDIRand SIGPIPE-safe shutdown- Dashboard streams the Go run alongside JVM runs
stove-kafka — Go Kafka bridge library¶
New Go library at go/stove-kafka enables shouldBePublished and shouldBeConsumed assertions for Go applications. The bridge forwards produced/consumed/committed messages over gRPC to Stove's observer.
import stovekafka "github.com/trendyol/stove/go/stove-kafka"
bridge, _ := stovekafka.NewBridgeFromEnv() // nil in production — zero overhead
defer bridge.Close()
Three first-party client integrations:
| Library | Subpackage | Integration |
|---|---|---|
| IBM/sarama | stove-kafka/sarama |
ProducerInterceptor / ConsumerInterceptor |
| twmb/franz-go | stove-kafka/franz |
kgo.WithHooks(&franz.Hook{...}) |
| segmentio/kafka-go | stove-kafka/segmentio |
ReportWritten() / ReportRead() |
Other clients (e.g. confluent-kafka-go) can use the library-agnostic core: bridge.ReportPublished(), bridge.ReportConsumed(), bridge.ReportCommitted(). All Bridge methods are nil-safe — the bridge disappears in production where STOVE_KAFKA_BRIDGE_PORT is unset.
MCP server in stove CLI¶
The CLI now exposes a local Model Context Protocol endpoint so AI agents can triage failed tests through compact, structured tools instead of loading entire logs into context.
$ stove
Stove CLI v0.24.0 running
UI: http://localhost:4040
REST: http://localhost:4040/api/v1
MCP: http://localhost:4040/mcp
gRPC: localhost:4041
Generic MCP client config:
{
"mcpServers": {
"stove": {
"transport": "streamable-http",
"url": "http://localhost:4040/mcp"
}
}
}
Tools (all read-only, local-only):
| Tool | Purpose |
|---|---|
stove_apps |
Apps recorded in the dashboard database |
stove_runs |
Runs, filterable by app and status |
stove_failures |
Default entrypoint — failed tests grouped by app and run |
stove_failure_detail |
Compact failure packet for one exact test |
stove_timeline |
Ordered test actions, failure-focused |
stove_trace |
Critical path and exception evidence from correlated spans |
stove_snapshot |
System snapshot summaries with targeted JSON drill-down |
stove_raw_evidence |
Capped raw lookup for one entry, span, or snapshot |
Defaults are token-aware: payloads are truncated deterministically, sensitive keys (authorization, cookie, password, secret, token, apiKey, credential) are redacted before return. Use budget: tiny|compact|full to dial detail.
The endpoint accepts loopback only and rejects non-local Host/Origin headers. See MCP.
Go integration test coverage¶
Stove black-box tests can now collect Go integration coverage. Build with go build -cover, set GOCOVERDIR, and Go writes coverage data on graceful shutdown — fits the stove-process and stove-container lifecycle.
./gradlew e2eTestWithCoverage -Pgo.coverage=true
./gradlew e2eTest-containerWithCoverage -Pgo.coverage=true
Notes:
- No framework changes — uses existing
envMapperand Gradle tasks signal.Ignore(syscall.SIGPIPE)inmain()is required so log writes to a closedProcessBuilderstdout pipe do not kill the process before counters flush- For container mode, bind-mount a host coverage directory into the container
See Go Process Mode — Coverage.
Improvements¶
ReadinessStrategy.HttpGetreplaces the olderHealthCheckOptionsAPI consistently across the codebase (process, container, provided application). Old callers should migrate to the new strategy.ProcessApplicationUnderTestexposes background stdout reading and a configurable graceful shutdown timeoutContainerApplicationUnderTeststreams container logs through SLF4J with the image as prefix
Documentation¶
- New "Other Languages & Stacks" section split into mode-focused pages: Process Mode and Container Mode
- New Container AUT component page — language-agnostic
stove-containerreference - New MCP component page covering discovery, integration, agent workflow, tools, token budgeting, and security
- New Provided Application page for black-box / smoke testing
- New Multiple Systems page for keyed system registration
- Coverage walkthrough (Gradle wiring,
GOCOVERDIR, SIGPIPE) in the Go pages - Refreshed other-languages/index.md with process vs. container guidance
Migration Guide¶
From 0.23.0 to 0.24.0¶
This is a non-breaking release for JVM users. New modules are opt-in.
Adopt black-box / smoke testing¶
If you want to run your existing Stove tests against a deployed app (staging, pre-prod), swap your framework starter for providedApplication() and use the *.provided(...) factory on each external system. No new dependency required — providedApplication() ships with com.trendyol:stove.
Register multiple instances of one system type¶
Define SystemKey singletons and pass them as the first argument to system DSLs (postgresql(AppDb) { ... }, httpClient(OrderService) { ... }). Default and keyed instances coexist.
Adopt non-JVM testing¶
For Go (or any language) applications, add either or both:
testImplementation("com.trendyol:stove-process") // host binary
testImplementation("com.trendyol:stove-container") // Docker image
For Go Kafka assertions, add the bridge to your Go module:
Adopt MCP¶
Upgrade the stove CLI to 0.24.0:
Point your agent runtime at http://localhost:4040/mcp. No test code changes required — MCP reads from the same dashboard database that already records your runs.
HealthCheckOptions → ReadinessStrategy¶
If you copied internal helpers from earlier snapshots, replace HealthCheckOptions with ReadinessStrategy.HttpGet(url, ...). Public APIs already used ReadinessStrategy, so most users are unaffected.