A tester runs the login test case, clicks Login and nothing happens. So they open the bug tracker and log this masterpiece:
Title: Login broken
Steps: Log in
Actual: Cannot log in
Expected: Can log in
Done. Assigned to a developer.
The developer now has to ask which build, which account, whether the page froze or showed an error, whether a request went out, and whether it happens every time or only when Mercury is in retrograde. The report has not helped anyone fix anything. It has merely made the tester's sighting of Something Weird™ official.
Before logging it
A failed test case is not automatically a bug. The test data may have expired, the environment may be dead, the requirement may have changed while the test case did not, or I may simply have missed a step.
Before logging anything, rerun it at least once and check the basics:
- Did I follow the steps and preconditions correctly?
- Are the build, environment and test data correct?
- Where did the expected result come from: a requirement, acceptance criteria, or just my opinion about how it ought to work?
- Can I reproduce it? If it is intermittent, roughly how often does it happen?
You do not need to investigate until you find the exact line of broken code. That is work for the team. You do need to establish that there is an observable difference between actual and expected behaviour.
A title that tells people what they are about to touch
Login broken, App crash and UI wrong may all be technically true. They are also useless without context.
A decent title usually answers three things: what happened, where, and under what condition.
For example:
[Login] User remains on Login page after submitting a valid admin account
Not every title needs all three clauses squeezed into it. If the whole app crashes, [Checkout] App crashes when applying an expired voucher says enough. Do not turn the title into a novel, but do not make people open the bug just to discover which screen it belongs to either.
Environment and data
If a bug appears only in Safari and the report says only Web, the developer can spend all afternoon testing Chrome and find precisely nothing. If it happens only to an account created last year and the account is missing from the report, same story.
Useful details often include:
- Environment: Test, Staging or Production.
- Build/version, or the commit if the team uses one.
- Device, OS, browser and version when relevant.
- Test account, role, data state or record ID.
- Frequency:
5/5,2/10, or “seen once so far”.
That does not mean pasting the computer's entire family tree into every issue. Screen resolution probably will not help when an API returns the wrong total. Include what could plausibly affect reproduction.
Steps should be as short as possible, but not shorter
The steps are the shortest route that still takes another person to the same failure.
For example:
- Open the Login page in the Test environment.
- Enter account
admin_01and a valid password. - Click Login.
If the precondition already says the user is on the Login page, every bug does not need “open Chrome”, “enter URL” and “wait for page to load”. On the other hand, if the bug appears only after logging out and returning with the Back button, removing that detail makes the issue impossible to reproduce.
This is why copying all 25 steps from a long test case into a bug report is rarely helpful. A test case proves the flow. A bug report isolates the break.
Expected and actual should bite into each other
Put these two side by side and the difference should be obvious.
Expected Result
User is redirected to
/dashboardand the account overview is displayed.
Actual Result
User remains on
/login. The button stops showing the loading state after about two seconds and no error message is displayed.
Actual means what I observed, not my guess at the cause.
The login API is broken, so the UI does not redirect.
That may be true, but without network data or logs it is still a guess. POST /api/login returned 500 is solid when there is evidence. If all I saw was a frozen UI, I should say the UI froze.
The developer needs a place to begin investigating. They do not need the tester reading tea leaves over the backend.
Evidence: screenshot, video or logs?
If the UI is visibly crooked and stays that way, a screenshot is enough. If a menu opens and closes by itself, an animation jumps, or the failure exists for two seconds, record a video. For API, console or performance problems, attach the relevant log, HAR or response.
Good evidence should show:
- Where the tester is.
- What action was just performed.
- How the failure appears.
- A timestamp or request ID when the server logs need tracing.
A razor-sharp crop of a Something went wrong popup, with the URL, time and preceding action removed, is still a beautifully photographed pile of zero information.
The same goes for video. Cut the first two minutes of waiting, but do not cut away the precondition that causes the bug.
Severity and priority
Severity is how much damage the issue does. Priority is how urgently it needs fixing. They are related, but they are not the same thing.
If no account can log in, both will almost certainly be high. A crash on an admin page used once a year may have high severity but lower priority right now. A campaign banner with the wrong logo does not break a function, so severity is low; if the campaign starts tomorrow morning, priority may shoot to the top.
A tester can propose both. Depending on the team's process, priority usually also needs input from the Product Owner, BA or whoever owns the business decision. Defect triage does not need to become a contest to see who can say “critical” loudest.
A complete bug report
Put the opening example back together:
| Field | Content |
|---|---|
| Title | [Login] User remains on Login page after submitting a valid admin account |
| Environment | Test · build 2026.08.09-rc2 · Chrome 139 · Windows 11 |
| Precondition | Account admin_01 is active and has the Admin role |
| Steps | 1. Open /login 2. Enter valid credentials 3. Click Login |
| Expected | User is redirected to /dashboard and account overview is displayed |
| Actual | User remains on /login; loading ends after about two seconds; no error message appears |
| Reproducibility | 5/5 |
| Evidence | Video, network response and request ID attached |
| Severity | High — blocks the main flow for an active account |
The person receiving this report still has to debug it, obviously. But they do not have to come back and ask where the bug lives or how to make it happen.
Write it so the team can fix it
A bug report is a working artefact, not a police report naming the person who committed the crime. Lines such as “developer coded it wrong”, “even the basic case fails”, or tagging half the company for extra pressure do not make a defect disappear any faster.
Write what you observed, attach enough evidence, and answer when the person fixing it needs more information. If the developer cannot reproduce it, open the same build and the same data together and look again. The report may be missing something, the environments may differ, or another change may now be hiding the defect.
The goal is simple: after reading the bug, the next person knows what to run, what to look at and why fixing it deserves attention. Whether the developer wants to fix it is another matter, but at least they will not be fixing it blindfolded.