Driving your service: HTTP, gRPC, a browser and a shell

clientsblack-box testing
Contents

A scenario never calls your code. It uses your service the way a person or another system does, through a client: an HTTP request, a gRPC call, a click in a browser, a command in a shell. The client is the scenario’s hands; the Then steps are its eyes.

How it works

A scenario tells a client what to do; the client uses the service the way a person or another system would, and the scenario checks what came back.tomato runreads the scenario, drives the client, checks the answerthe scenarioWhensends "POST" to …Thenresponse status is …features/*.feature"todos-client"http-client resourcedoesPOST /api/todos{"title": "Buy milk"}gets back201{"id": 1, "title": "Buy milk"}todosyour serviceHTTP API :3000gRPC API :50051web page /CLI todo add …

Start. tomato starts your service and its dependencies. The client only needs to know where the service is: an address, or nothing at all for the shell.

Act. A When step tells the client what to do, and it does it the way another service would: it sends a request.

Answer. The service answers through the same door: a status, headers and a body.

Assert. Then steps check that answer. Check the effects too, through the other resources: the row in the database, the message on Kafka.

Reset. Before the next scenario the client forgets its headers and cookies, so no scenario leans on another's.

The same loop for every client:

  1. Act. A When step makes the client do one thing.
  2. Answer. The service answers through the same door.
  3. Assert. Then steps check the answer.
  4. Reset. The client forgets everything before the next scenario.

Which client

Your service hasClientActs withChecks
an HTTP APIhttpsends "POST" to "/api/todos" with json:status, headers, JSON
a gRPC APIgrpccalls "todos.v1.TodoService/AddTodo" with:status code, JSON of the message
a web pagebrowserfills "New todo" with "…", clicks "Add"what the page shows
a command lineshellruns "todo add Buy milk"exit code, stdout, stderr, files

Name a client after the service it calls. "todos-client" sends … says who is being called; "api" sends … makes the reader open tomato.yml to find out. The same goes for the rest of the suite: stripe-stub, todos-db, alice-browser.

The answer is half of it

A client sees what comes back through its door. What the service did lives elsewhere: the row it wrote, the event it published, the call it made to a third party. Check those with the resources that see them (postgres, kafka, the stubs), so a scenario proves the effect, not only the reply.