Keep your application healthy.
tomato tests a service from the outside. It starts the service's real dependencies, stands in for the services it calls, and runs plain-English scenarios against it, whatever language it is written in.
brew install tomatool/tap/tomato
The one-minute introduction · watch on YouTube
Describe the world, then the behaviour
tomato.yml says what your service needs. Scenarios say what it
should do, including the effects other services see: the row it wrote,
the message it published, the call it made.
containers: postgres: { image: postgres:16-alpine } kafka: { preset: kafka } app: command: ./bin/orders # any language port: 8080 resources: api: { type: http, base_url: http://localhost:8080 } db: { type: postgres, container: postgres } events: { type: kafka, container: kafka } catalog: { type: grpc-server } # a stub
Scenario: An order is stored and announced Given "catalog" stub "catalog.v1.Catalog/GetProduct" returns json: {"sku": "TOMATO-1", "price": 250} When "api" sends "POST" to "/orders" with json: {"sku": "TOMATO-1", "quantity": 4} Then "api" response status is "201" And "api" response json "id" saved as "{{order_id}}" And "db" table "orders" has "1" rows And "events" receives from "orders.created" within "10s"
Everything a service talks to
Real dependencies in containers, stand-ins for the services you call, and one Gherkin vocabulary across all of them.
🐳 Real dependencies
Postgres, Kafka, RabbitMQ, Redis, S3, ScyllaDB start in containers, reset before every scenario so scenarios never leak into each other.
🎭 Stubbed neighbours
HTTP and gRPC servers that stand in for the services you call: stub answers, fail on purpose, assert on exactly what your service sent.
🌐 Any language
tomato only talks to your service over the network, so the same suite tests Go, Rust, Kotlin, Python or Node.js, and survives a rewrite.
☁️ AWS, like production
An aws resource gives your app an IAM role through IRSA, and the Kafka preset speaks MSK's AWS_MSK_IAM authentication.
🖥️ tomato ui
Browse the suite, see each scenario's flow and the topology of what it touches, and run scenarios from the browser.
✅ Made for CI
A GitHub Action, JUnit and Cucumber reports, PR comments, and tomato coverage to catch steps that match nothing.
Where to next
Start with the docs, read the blog for the practice around it, or open the source.