tomato
Behavioral testing toolkit

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.

tomato.ymlthe world
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
features/orders.feature✓ passed
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.

httphttp-servergrpcgrpc-server postgresscylladbrediskafka rabbitmqs3websocketwebsocket-server shellawsbrowserpdflifecycle