7 Software Testing and Quality
Learn how software testing provides evidence about product behavior, how to select and automate useful tests, and how debugging and quality assurance help teams improve software.
Purpose of testing
gathers evidence about whether software behaves as expected and helps reveal defects. It can show that particular behaviors passed or that a failure occurred under particular conditions, but it cannot prove that a program is defect-free. Software quality also depends on practices that prevent defects and improve how software is developed.
and scope
organize testing by the scope of the software being examined. They may overlap, particularly in iterative development, and differ from test types: functional or performance tests, for example, can be performed at more than one level.
checks an individual function, class, or module in isolation. One example is checking whether a tax-calculation function returns the correct result for a given price.
Component integration testing checks interactions and interfaces between components, such as whether a cart correctly passes item totals to a payment component.
System testing checks the behavior of the complete product against its requirements. An end-to-end test might place an order and verify the resulting confirmation.
System integration testing checks connections between the product and external systems, such as a payment provider or shipping service.
Acceptance testing evaluates whether the product meets user or business needs and is ready for use. Intended users or other authorized stakeholders may perform it.
Terms and boundaries can vary by team. When choosing a level, consider what part of the system is being tested and what decision the result should support.
Designing useful tests
A describes conditions, inputs, actions, and expected results. A clear test typically follows this sequence:
Arrange the needed context.
Act by triggering one behavior.
Assert the expected result.
Clean up any state the test created.
Choose cases based on requirements, risks, and the system’s structure, rather than only on typical usage. Test expected use as well as invalid, unusual, or boundary conditions; this gives stronger evidence than testing only the happy path.
Techniques for selecting cases
divides inputs into groups expected to behave alike, then tests representative values from valid and invalid groups. If a discount applies to purchases of at least 10 items, useful groups are fewer than 10 and 10 or more.
checks values at and near group boundaries. For that discount rule, test 9, 10, and 11 items; off-by-one defects often occur at limits.
Decision tables test combinations of conditions and their outcomes. For example, a table can record how membership status and order value together determine a discount.
State-transition testing checks valid and invalid changes between states. For example, check whether an unpaid order can be cancelled and what happens after it has shipped.
Structure-based testing uses knowledge of code paths to check statements or branches. Code coverage indicates which parts ran, but does not by itself show that behavior is correct or that meaningful cases were tested.
Exploratory testing uses purposeful scenarios to learn about the product, with observations guiding further tests. It can complement planned cases by revealing unexpected interactions.
Prioritize tests around likely defects and their consequences. A payment failure, for example, may deserve more attention than a minor layout issue.
Automating repeatable checks
uses tools and scripts to run checks and compare actual results with expected results. It is especially useful for repeatable checks, such as unit tests, API checks, and , because these can run frequently as code changes.
Automation can improve speed and consistency, but it does not replace human judgment. Exploratory testing, usability evaluation, and unclear requirements often need human investigation.
Good automated tests are focused, readable, repeatable, and isolated from one another. Tests that share mutable data or depend on execution order can fail unpredictably; separate test data and cleanup help prevent this. Automation also has costs: tests must be designed and maintained, and failures must be diagnosed. Automate checks whose repeated value justifies that work, and investigate unreliable tests rather than routinely ignoring them.
Diagnosing and retesting defects
Testing exposes evidence of a problem; investigates and removes its cause. A practical cycle is to reproduce the failure, narrow down and diagnose the defect, and then make a fix.
After the fix, run a to check whether it resolves the reported issue. Then run to check that existing behavior has not been broken.
A useful defect report records the steps to reproduce the failure, expected and actual results, relevant environment details, and helpful evidence such as logs. A minimal, repeatable example makes diagnosis easier.
Quality assurance in the development process
and testing are related but not interchangeable. Testing is primarily product-oriented: it evaluates software and helps identify defects. QA is process-oriented and preventive: it improves the practices used to develop and test software. QA is the responsibility of the whole project team, not only a separate testing group.
Practical quality practices include:
Reviewing requirements and code.
Defining acceptance criteria.
Using consistent development and test processes.
Running automated checks regularly.
Tracking defects and risks.
Using retrospectives to improve the process.
Test findings can support immediate fixes and longer-term improvements. For example, repeated failures caused by ambiguous requirements may indicate a need to improve how requirements are reviewed.