Software Testing

From Reading the Spec to Catching the Right Bug: Real-World Lessons from a Tester

Friday, 30 Oct 2026 9 min read 22 views

Introduction: testing is more than clicking through a script

Many people outside the industry picture a tester's job as opening a pre-written test case and clicking through the buttons in order. That is only the surface of the work. When a product ships and users hit trouble, the tester is the first person asked: how did this bug slip through?

I wrote this after several years of QA work across fintech, e-commerce, and SaaS. The twelve lessons below are not textbook theory. I paid for them with time, tense arguments, and apologies to customers.

Program testing can be used to show the presence of bugs, but never to show their absence.

Edsger W. Dijkstra, Notes on Structured Programming, 1970

The twelve lessons at a glance

#LessonOne-line takeaway
1Ask, do not guessEvery ambiguity in the spec becomes a question, not an assumption.
2Happy path firstHalf your time goes to the flow most users actually take.
3Two layers of sightFeel the journey as a user, then inspect it as an engineer.
4Four data statesEmpty, loading, overload, error. Never just the pretty case.
5Suggest improvementsDo not stop at a deviation; propose a concrete fix.
6Severity vs priorityTechnical impact and business urgency are different axes.
7Evidence, not emotionA bug report is a forensic record, not a complaint.
8Open F12 firstNo request means frontend; 500 or timeout means backend.
9Database is truthA green banner is not proof that the data is correct.
10Butterfly effectRetest every flow that shares the code you changed.
11Users are messyDouble clicks, back buttons, pasted text, long names.
12Developers are alliesPut both of you on the same side of the problem.

Part 1: Thinking about business requirements

Lesson 1: Read the spec to ask questions, not to guess

The trap: Skimming the document and filling every gap with personal intuition, because asking feels like bothering the BA or the developers.

  • Read with a pen and underline every ambiguity.
  • Ask what-if questions: What if the network drops mid-payment? What if the user cancels at the last step? What if two people pay the same order at once?
  • Turn every answer into an explicit test criterion.

Takeaway: A syntax error costs minutes. A misunderstood requirement costs hundreds of hours.

Lesson 2: Protect the happy path before hunting for edge cases

The trap: Rushing into exotic edge cases on a new build while the core registration or payment flow is still broken.

  • Spend about 50 percent of the time on the happy path most users take.
  • Spend about 30 percent on common input errors.
  • Spend the last 20 percent on extreme and boundary cases.

Takeaway: Nobody tests 100 percent of every case. Prioritise the flows where a small bug costs money or trust.

Part 2: The experience lens

Lesson 3: Two layers of sight, from user feeling to a technical magnifying glass

The trap: Two wrong extremes. One is chasing pixel misalignment and missing how the journey feels. The other is clicking through without noticing the layout breaking at other screen sizes.

  • First five minutes: play a new customer in a hurry, mouse only.
  • Then open the responsive tool and inspect buttons, spacing, and visual priority at each width.

Takeaway: Feel the product as a user, then inspect it as an engineer.

Lesson 4: Think in four data states

The trap: Testing only with pretty sample data and forgetting the first-run, slow-network, heavy-data, and failure experiences.

  • Empty: an illustration, a short explanation, and a create button.
  • Loading: disable the button and show an inline loader to stop double clicks.
  • Overload: test 100-plus character names, very long lists, and missing optional fields.
  • Error: explain what happened and how to recover.

Takeaway: Four states are the minimum bar for any screen.

Lesson 5: Do not stop at finding bugs, contribute improvements

The trap: Letting a clunky feature pass with the excuse that the spec said so.

  • Record an improvement suggestion with a concrete solution, not just a deviation.
  • Example: merge two address fields and auto-fill from the postal code, instead of writing that the form is clunky.

Takeaway: Proposals with solutions get heard.

A bug report is a forensic record, not a complaint.

Part 3: Catching bugs with objective evidence

Lesson 6: Separate severity and priority clearly

The trap: Marking every bug as urgent, which creates tension and hides the bugs that really are serious.

  • Severity measures technical impact: a crash, data loss, a broken core feature.
  • Priority measures business urgency: a wrong logo does not crash the site, but it must be fixed at once.

Takeaway: Two independent axes. When everything is red, nothing is.

Lesson 7: Speak with objective evidence, not emotion

The trap: Reporting that the screen sometimes breaks or that the interface is slow.

  • Numbered reproduction steps.
  • Actual result next to expected result.
  • An annotated screenshot or video.
  • HTTP status and trace ID from the Network tab.

Takeaway: Enough evidence turns half a day of investigation into a five-minute fix.

Lesson 8: Open F12 before reporting, and tell Frontend from Backend

The trap: Blaming the backend before checking whether the interface even sent a request.

  • No request after a click: frontend, likely a missing handler or blocked validation.
  • 200 but nothing rendered: frontend display bug.
  • 500 or timeout: backend bug.

Takeaway: Three branches save the team many round trips.

F12 triage decision tree

Figure 1. Triage the bug in the Network tab before assigning it.

Lesson 9: The interface is only a shell, the database is the truth

The trap: Seeing a success message and marking the case as passed.

  • Query the record directly by ID.
  • Check secondary fields, timezone, and change history.
  • For payments, permissions, and system settings, database verification is mandatory.

Takeaway: A green banner is not proof. A correct row in the database is.

A green banner is not proof. A correct row in the database is.

Part 4: Systems thinking and empathy

Lesson 10: The butterfly effect, fix one place and another may break

The trap: Checking only the field the developer fixed and closing the ticket.

  • Retest every flow that shares the component, validation, or service layer you touched.
  • Treat regression as part of the fix, not an extra step.

Takeaway: One shared function can break three screens.

Lesson 11: Real users never operate as neatly as the script

The trap: Testing slowly and sequentially, then assuming users will behave the same way.

  • Press confirm repeatedly and check for duplicate orders.
  • Hit the browser back button in the middle of checkout.
  • Type complex diacritics, paste from Word, and upload files with long names.

Takeaway: Untidy actions expose the bugs a tidy script never touches.

Lesson 12: Do not turn developers into opponents

The trap: A nitpicking attitude that turns the developer into an opponent.

  • Replace "your code is broken" with "when I send this data, the system responds like this; could you take a look?"
  • Put both of you on the same side of the problem.

Takeaway: Respect and technical empathy make work flow faster than any tool.

Appendix: three practical tools

Tool 1: The forensic bug report template

A standard bug report has five parts. The title follows the pattern of module, frequency of 100 percent or random, and the incident under the trigger condition.

  1. Test environment: device and OS, browser and version, environment and build number, and the test account with its role.
  2. Minimal reproduction steps: numbered and short enough for anyone to repeat exactly.
  3. Actual result: what happened, the waiting time, and the message shown, verbatim.
  4. Expected result: the correct behaviour under the business rules, including inline validation and a disabled Save button after the first click.
  5. Technical evidence: an outlined screenshot or video, the request URL, HTTP status, response time, request payload, response body, and trace ID.

Tool 2: The severity and priority matrix

The risk score is the severity weight multiplied by the priority weight. It gives the team an objective order for fixes.

Severity and priority matrix

Figure 2. Severity measures technical impact; priority measures business urgency.

LevelSeverity 1: CatastrophicSeverity 2: MajorSeverity 3: ModerateSeverity 4: Minor or cosmetic
Priority 1: Urgent, fix within 2 to 4 hoursPayment gateway down, card data leaked, primary database connection lost.Discount codes fail during a flash sale, verification emails are not delivered.A major partner's logo is wrong on the home page, the brand name is misspelled in a press release.The app icon is misaligned on a press event build.
Priority 2: High, fix in the current sprintThe accounting tax report has a calculation bug that can be worked around manually for now.Date filters are off by timezone for a group of sub-accounts.The notification panel close button is misaligned on iPad Safari.The contact page heading font is 2px off from the design system.
Priority 3: Normal, add to the backlogA memory leak in the legacy backup job that runs once a quarter.Profile photos cannot be changed with a webp file.The side menu has no transition animation.The footer background is darker than the specified colour.
Priority 4: Low, fix when there is spare timeA process conflict in a data export tool scheduled for replacement next month.Formatting issues in an internal report used by only two IT staff.A single word on the Terms of Service page that does not affect meaning.The bottom margin on the 404 page is too wide at 300px.

Tool 3: The four UI states checklist

Four UI data states

Figure 3. Four states every screen must survive.

1. Empty state.

  • ☐ Never leave a blank screen or an unexplained empty table.
  • ☐ Show an illustration that fits the context.
  • ☐ Add a short heading and a friendly explanation.
  • ☐ Provide a primary button that leads to the first item.

2. Loading state.

  • ☐ Use a skeleton screen that mirrors the coming layout.
  • ☐ Disable the confirm button and show an inline loader.
  • ☐ On Slow 3G, the layout must not break after 5 seconds, and long tasks should report progress.

3. Overload and partial data.

  • ☐ Paste 500 characters with no spaces; the layout must wrap or truncate with a tooltip.
  • ☐ For 1,000 to 10,000 records, use virtual scrolling or pagination.
  • ☐ With optional fields missing, the layout stays balanced.

4. Error state.

  • ☐ Offline: show a banner and a retry action.
  • ☐ 5xx: apologise with a trace ID and never expose a stack trace or database error.
  • ☐ Validation: mark the field in red, show the fix below it, and scroll to the first invalid field.

References and further reading

Closing

Testing is not a race to find the most bugs. It is how the team keeps the user's trust intact. If you take one habit away, take this one: ask before you assume, and check the real data before you trust the banner.

Ready to Transform Your Business?

Let's discuss how we can help you leverage AI and digital transformation for your enterprise.

Frequently asked questions

How do severity and priority differ?
Severity measures technical impact, such as a system crash or data loss. Priority measures business urgency. The two are independent: a wrong logo has low severity but high priority because it directly affects the company image. Separating them helps the team fix things in the right order without unnecessary tension.
Why should testers check the database when the interface reports success?
The interface is only the display layer. Many cases show success while the stored row is missing fields, has the wrong timezone, or never logs a change history. For features such as payments, permissions, or system settings, querying the record directly by ID is mandatory to confirm the data is actually correct.
How do you tell Frontend from Backend bugs with F12?
Open the Network tab and repeat the action. If no request appears after a click, it is a frontend bug from a missing event handler or blocked validation. If the request returns 200 but nothing renders, it is a frontend display bug. If it returns 500 or times out, it is a backend bug for the server team.
What are the four UI data states testers should check?
Empty, loading, overload, and error. The empty state needs an illustration and a create button; the loading state must disable buttons to prevent double submission; the overload state must handle long text and large lists; the error state needs a clear message and a way to recover.
What does a proper bug report contain?
A proper bug report has five parts: test environment, minimal reproduction steps, actual result, expected result, and technical evidence. The evidence should include annotated screenshots or video, the HTTP status, request payload, response body, and trace ID so developers can fix it quickly.

Share this article