A blog about testing ·

How to write a bug report that gets accepted: structure, steps and common mistakes

A bug report is not paperwork. It is read by a person who has to reproduce the defect on their machine, work out how bad it is and decide whether to fix it now or after the release. A report that does not give them that comes back with questions, and both sides lose time.

What a report is made of

The minimum working set is nearly the same everywhere: title, environment, steps to reproduce, expected result, actual result. Severity, attachments and logs come on top — but without those five there is no report.

There is an easy self-check: hand the report to someone who knows nothing about the task. If they reproduced the defect without asking a single question, the report is done.

The title: what broke and where

A title is read in a list of a hundred lines, and people decide from it whether to open the thing. So it needs two facts: what exactly happens and in what place. «The cart is broken» contains neither.

A good title survives being cut down to one line in a list and still makes sense. A bad one has to be opened to find out what it is about.

Error in an order

POST /orders creates an order with an empty cart and returns 201

Steps to reproduce: exact data, not a retelling

A step is an action that can be repeated literally. «Send an invalid value» cannot be repeated: invalid values are endless, and half of them behave correctly. What is needed is the one value it broke on.

For an API that means the method, the full address with its parameters, the request body and the headers if they matter. For an interface, what was clicked and typed, word for word. Order matters too: a defect that only reproduces after signing in will not reproduce without that step.

1. Open the catalogue
2. Set a weird filter
3. Nothing gets filtered

1. GET /products?min_price=-500
2. Look at the status code and the number of items in data

The expected result comes from the requirements

The most common weakness in a report is an expected result invented on the spot. «It is expected that it should not be like this» is an opinion, not a requirement, and an argument about it can run forever.

The expected result is a quotation: a line from the requirements, an acceptance criterion, a point in the documentation, the behaviour of a neighbouring method that was built correctly. If there is nothing to quote, this is not a defect yet but a question for the analyst — and it is worth raising it as exactly that.

The actual result, in contrast, is written with no interpretation: status code, body, a specific number. Not «the total was calculated wrong» but «the answer has total = 1380 for two items at 690 with a 10% promo code».

Five mistakes that get a report sent back

  1. Two defects in one report. One gets fixed, the whole thing gets closed, and the second ships.
  2. Steps from memory. One thing is written, another was sent, nothing reproduces.
  3. Judgement instead of fact: «everything is broken», «works terribly». It is not clear what to fix.
  4. No environment. Which stand, which user, with what rights.
  5. A duplicate. Before filing it is worth searching — the board often already has one.

A complete API bug report example

This is a working example rather than a universal form. It connects the observation to the contract and preserves the exact request instead of a summary from memory.

A defect reproducible without its author
Title: POST /orders creates an order for an empty cart and returns 201\nEnvironment: QA, build 2026.09.21-3, user qa-buyer-17\nPrecondition: the user cart is empty\n\nSteps:\n1. Send POST /api/v1/orders with a valid Bearer token\n2. Request body: {}\n3. Send GET /api/v1/orders\n\nExpected: 422; no order is created (AC-ORD-04)\nActual: 201; order_id=8412, total=0 is created\nReproducibility: 3/3\nEvidence: request/response HAR, correlation_id=7af2…

Never paste a live token, password, personal data or a full production dump. Mask secrets, replace personal data with synthetic values and share sensitive logs through the agreed security process.

Checklist before submission and retest

Severity describes impact; priority describes the business order of fixing. Scales and owners vary by team, so the rationale matters most. After Fixed, QA repeats the original steps on the stated build and checks the closest regression risk instead of closing from a developer comment.

  1. The title includes the action, incorrect result and affected area.
  2. Build, environment, role, preconditions and exact test data are present.
  3. Expected points to a criterion, contract or recorded decision.
  4. Actual contains observable facts: status, values, time, ids and frequency.
  5. Attachments open, secrets are masked and one report covers one defect.
  6. Retest covers the original scenario, the fixed build and nearby regression.

Common bug-report questions

Should I report a defect that happened only once?

Yes when the impact is meaningful and evidence exists. State the frequency, exact time, data and logs without claiming stable reproduction. A rare payment failure matters more than a reliably misaligned margin.

Who sets severity and priority?

There is no universal rule. QA often proposes severity while product or triage owns priority, but a team may work differently. Shared definitions and a written rationale matter more.

What if there is no requirement?

Record the behaviour and risk as a question or discovery item, obtain a product decision and then define expected behaviour. A personal preference is not automatically a defect.

A report is a working document, and the only way to learn to write one is to write a few dozen: on a real defect, not on an invented example.

Practise on live services Next write-up

← All write-ups