Steps to Reproduce in a Bug Report: How to Write Them
November 2, 2026 · 3 min read · by the Tracebird team
Good steps to reproduce are numbered, one action per line, and start from a known state. Add the expected result and the actual result, and a developer can trigger the bug without asking you a single question.
Most bug reports fail on this one field. "Checkout is broken" tells nobody what to click. Here is how to write steps that actually reproduce the bug, and what to stop typing by hand.
Start from a known state
A step list is only useful if the reader begins where you began. Write the starting point first: which build, which environment, which account, logged in or not.
- App version or build number (for example 1.4.2)
- Environment (staging, production, TestFlight build)
- Device, OS and browser
- Account type or any flag that changes the behavior
If the bug only shows up for a user with an empty cart or an expired plan, say so before step 1. That single line removes most "cannot reproduce" replies. If you keep hitting them, see Cannot Reproduce a Bug From a User Report? Do This.
One action per line, in the words of the interface
Number every step and keep each one to a single action. Use the labels the screen shows, not your own names for them.
Bad:
- Go to the payment page and try to pay.
Good:
- Open the app and sign in as a user with one item in the cart.
- Tap Cart, then Checkout.
- Enter the test card 4242 4242 4242 4242, any future expiry date.
- Tap Pay.
Name the exact button, include the exact input, and keep the order. If a step depends on timing, such as tapping twice quickly, write that down too.
Say what you expected and what happened
Finish with two short lines. They turn a list of clicks into a bug.
- Expected: the confirmation screen appears.
- Actual: the Pay button spins forever, nothing is charged.
Add how often it happens. "Every time" and "1 out of 5 tries" lead a developer to very different causes.
Test your own steps once
Before sending, follow your list from a fresh start, as if you were someone else. Steps drift from what you really did: a skipped login, a setting you forgot you had changed. If the bug does not appear, one of those missing details is probably the cause, so add it.
Keep the data safe too. Use test accounts and fake values instead of real customer details, so anyone on the team can run the steps.
Stop typing what a tool can capture
Steps are the part only a human can describe. Everything around them can be collected automatically: console errors, failed network calls, the environment, and a replay of what led to the bug. Writing "I think the request failed" is slower and less reliable than attaching the request with its status code.
That is the idea behind Tracebird: the tester circles the problem, writes one sentence, and the report arrives with console logs, network calls and session replay already attached. Your testers never need a template. To see what each piece is worth, read How to Get Console Logs From a User and Screen Recording vs Session Replay for Bug Reports.
A template you can copy
Environment: app/build version, staging or production, device, OS, browser
Starting state: account type, data, flags
Steps to reproduce:
1.
2.
3.
Expected:
Actual:
Frequency: always / sometimes (x out of y)
Paste it where testers file bugs, or let the tool fill in the environment and logs for them so the testers only write the steps and the two result lines.