Ideas, case studies, and tips for improving the quality of customer service.

Software Testing Best Practices: 9 Methods in Action

Software testing best practices become useful when they change how you check a specific feature. Test-driven development, continuous integration, exploratory testing and risk analysis answer different questions. Combining them should produce clearer evidence, rather than a larger collection of tests nobody trusts.

This guide follows one illustrative feature: a workspace member uploads a document, an interrupted upload can resume, and the completed document appears once in the correct workspace. The feature and proposed checks are fictional, not a case study or a tested implementation. For broader team standards and release governance, use our quality assurance best practices.

Choose the practice for the question you need to answer

Practice Question in the upload example Useful evidence
Test-driven development Does the upload-state rule behave correctly? A focused check that fails before the behavior is implemented
Continuous integration Does this change work with the current shared code? Results tied to the integrated revision
Risk-based testing Which upload failures deserve the most scrutiny? Prioritized scenarios with likelihood and impact rationale
Automation pyramid At which layer can each risk be checked? Rule, service and journey checks with distinct purposes
Shift-left testing Are the requirements testable before implementation? Resolved questions about retries, limits and access
Behavior-driven development Do participants agree on customer-visible behavior? Agreed examples connected to acceptance checks
Exploratory testing What recovery behavior did our scripts overlook? Session notes, observations and unanswered questions
Test data management Can another person recreate the relevant state? Named fixtures with setup and cleanup instructions
Defect prevention and analysis Why did an important failure escape? Contributing factors and a reviewable prevention action

The rows describe complementary approaches. You do not need to introduce all nine as separate ceremonies. Start with the gap that currently prevents your team from making a sound decision.

Product demo: a customer recording in Screendesk with console logs and network requests captured alongside it.

1. Use test-driven development for a defined behavior

Martin Fowler’s description of TDD follows a short cycle: write a failing test, implement enough behavior to pass it, then refactor. The refactoring step keeps improving the design while the tests protect the agreed behavior.

For the upload feature, choose a narrow rule: a completed upload cannot return to the “receiving” state when a delayed retry arrives. Specify the initial state, attempted transition and expected outcome. Confirm the check fails because that rule is missing, rather than because its setup or imports are broken.

After implementing the rule, check the result and simplify the design without changing behavior. Avoid a test that merely repeats the implementation’s condition or asserts private method calls. The useful protection is the state transition’s externally meaningful result.

Decision: use TDD where the behavior is clear enough to express. When the upload protocol is still uncertain, investigate it first. A speculative test suite can lock in an assumption that the team never agreed to.

2. Make continuous integration produce actionable feedback

Fowler’s continuous integration guidance describes frequent integration into a shared codebase, verified by automated builds and checks. The operational question is whether a failure reaches someone who can investigate it while the change is still understandable.

In the example, a change to upload-state handling should be checked with the current storage and metadata code. Record the revision, relevant configuration and results. Keep quick rule checks close to the change; run broader integration checks at a cadence justified by their cost and risk.

A failed check should explain which outcome differed and retain enough context to investigate. If a rerun passes, preserve the original failure and determine whether it was an environment problem, an unreliable test or a real race condition. A passing retry is not a diagnosis.

Decision: define which failures block integration, who owns investigation and how a temporarily disabled check will be restored. Adding another pipeline stage without that ownership can create ignored noise.

3. Prioritize scenarios by product risk

The ISTQB Foundation Level syllabus relates product risk to likelihood and impact. Use that assessment to choose the depth and order of investigation, with assumptions visible to reviewers.

For this fictional feature, cross-workspace access, a corrupted completed file and duplicate documents after a retry deserve attention because they can affect confidentiality or data integrity. A progress-label alignment problem may be less disruptive, although accessibility or misleading completion status could change its impact.

  • Check that an upload identifier from one workspace cannot expose another workspace’s document.
  • Interrupt transfer at a controlled point and verify the completed content, not only the progress indicator.
  • Repeat a completion request and check that the required single document remains single.
  • Test rejection at the agreed size boundary and verify the recovery message.

Decision: record which risks remain untested and why. A ranked list guides effort; it does not prove every high-impact failure has been ruled out.

Risk table for an upload feature: cross-workspace ID, high impact, deep testing; corrupted file and duplicate on retry, high impact, deep; size boundary, medium, standard; progress label, low impact, light.
Example: upload scenarios ranked by impact and likelihood; confidentiality and data-integrity risks get deep checks, a progress-label issue lighter testing.

4. Put automated checks at an appropriate layer

Mike Cohn’s automation pyramid highlights unit, service and user-interface layers, including the often-neglected middle layer. Treat the model as a way to choose where evidence belongs, without imposing a universal percentage split.

In the upload example, use a focused rule check for allowable state transitions. Use an integration or service check for the interaction between completion requests, stored content and document metadata. Use a browser journey to check that a member can start, recover and find the uploaded document.

Each layer should have a reason. Running every invalid-size combination through the browser may add maintenance without improving the evidence. Checking everything through mocked units can miss a disagreement between real components. Keep the smallest check that can detect the relevant failure, then add a broader check where an actual boundary needs verification.

Decision: review repeated assertions and unreliable checks. Test count is less useful than knowing which risk a failure exposes.

5. Shift requirement questions earlier

Before implementation, ask what “resume” means. Does it reuse already transferred content? What happens after session expiry? Who may resume an upload created by another member? Does the application clean up abandoned uploads, and when?

Turn unanswered questions into explicit decisions with an owner. For example, the product owner might define how long an incomplete upload remains resumable, while engineering explains the storage constraints. A tester can then propose boundary cases at expiry and after a permission change.

ISTQB describes shift-left testing as bringing relevant activities earlier while retaining needed later testing. Early review cannot replace checking the actual storage integration or the complete recovery experience.

Decision: review the changed requirement before writing a large suite. If “completed” has no agreed meaning, a green test can confirm the wrong outcome.

6. Use BDD to agree on customer-visible examples

Cucumber’s BDD documentation connects discovery, formulation and automation. Start with a conversation between the people who define, implement and evaluate the feature. Structured wording helps once the example is understood.

Here is an illustrative acceptance example, not executable test code:

Given a member has permission to upload to Workspace A
And their document upload was interrupted before completion
When they resume it within the agreed retention period
Then one complete document is available in Workspace A
And the member can see that the upload completed

Discuss the missing details: how integrity is checked, whether the member’s permissions can change and what happens after expiry. Record separate examples for exceptions instead of burying every branch in one scenario.

Decision: automate stable examples that need ongoing verification. Using Given/When/Then syntax alone does not demonstrate shared understanding or produce a working check.

7. Explore recovery with a focused charter

ISTQB describes exploratory testing as learning, designing and executing checks together. Give the session a question so the investigation remains explainable.

For this feature, an illustrative charter is: “Investigate whether a member can understand and recover from an interrupted upload without accidentally creating duplicates.” Explore changing connectivity, navigating away, reopening the page and seeing an expired session. Use an authorized test environment and safe files.

Record the build, account state, actions, observations and coverage limits. Note confusing messages even when the file eventually uploads. At the debrief, separate confirmed defects, requirement questions and ideas that need further investigation.

Decision: turn a discovery into a permanent automated check when it represents a repeatable risk worth maintaining. Preserve useful exploratory evidence even when no new regression test is justified.

8. Make test data reproducible and purposeful

The same tiny text file under a single administrator account cannot represent every upload condition. Define fixtures for the scenarios that matter: an empty file if permitted, a boundary-size file, a file with recognizable content, an interrupted transfer and accounts with different workspace permissions.

For each fixture, document its purpose, creation steps, expected initial state and cleanup. Give concurrent runs separate upload identifiers so one check does not delete or complete another’s data. Retain failing artifacts long enough for investigation under your team’s access and retention rules.

Prefer synthetic files and accounts when they represent the scenario adequately. Any proposed customer-data use should follow the organization’s established review process. Removing one identifier does not by itself establish that data is anonymous.

Decision: reset data to a known state without erasing evidence that another investigator still needs.

9. Use defect analysis to improve the relevant protection

If an upload defect reaches customers, repairing it is only one part of the response. Investigate how it arose and which assumptions or checks failed to reveal it. Google’s SRE guidance emphasizes contributing causes and preventive actions in a blameless review.

Suppose, illustratively, an old retry creates a second document after completion. The investigation might examine the missing completion rule, how retry behavior was specified and whether tests used realistic request ordering. These are questions to investigate, not assumed findings.

An action should name an owner and completion evidence. A focused regression check may be appropriate; an unclear requirement may also need correction. Adding tests cannot repair every process or design weakness.

Decision: revisit the action when it is complete and check whether it addresses the identified risk. Avoid claiming a single “root cause” explains every contributing condition.

Put the nine practices into a small adoption plan

Choose one upcoming change and produce four reviewable artifacts: agreed examples, a prioritized risk list, results tied to a revision and a record of remaining uncertainty. Use our quality assurance procedures when you need a repeatable approval and exception process.

When a check fails, submit expected and actual behavior, a useful sequence, environment and impact. Our software bug report template connects that evidence to verification. A recording can support a visible failure, while written steps and relevant technical evidence preserve the investigation context.

After the change, review whether feedback arrived in time, failures were understandable and important risks were examined. Track unreliable checks and repeated escaped defect categories. Coverage percentages and passing test counts describe parts of the work; they do not establish that the product is defect-free.

Share this article
Shareable URL