What is Software Testing?

Technology — James William Steven Parker

Software testing is the systematic evaluation of software to find defects, provide evidence about behaviour and determine whether the software satisfies specified or expected requirements under defined conditions. Testing involves executing software in many common approaches, but it can also include activities such as static examination, model-based analysis and other techniques depending on the testing discipline and terminology used.

The central testing process involves defining conditions or inputs, exercising the relevant software behaviour and comparing the observed result with an expected result, requirement, property or other test oracle. Testing can be performed throughout development rather than only after implementation. Its purposes include finding defects, verifying implemented requirements, validating that software meets user needs, supporting regression control, assessing compatibility and providing information about risk and quality. Testing does not prove that software contains no defects in the general case.

Testing exists at multiple levels. Unit testing focuses on small components such as functions or classes, often in isolation. Integration testing examines interactions between components, services or systems. System testing evaluates the behaviour of an integrated application or system against broader requirements. Acceptance testing evaluates whether software is suitable for acceptance under specified business or user criteria. End-to-end testing exercises realistic workflows across multiple components and external dependencies.

The boundaries are not universally identical across organisations, but the levels differ primarily in scope and the relationships being examined. Testing at one level cannot completely substitute for another because a component can behave correctly in isolation while failing when integrated with another component, and a complete workflow can expose problems that individual unit tests do not represent.

Testing can also be classified by what it seeks to evaluate. Functional testing checks whether specified functions produce appropriate results, while non-functional testing evaluates properties such as performance, scalability, reliability, usability, accessibility, security and compatibility. Performance testing can include load, stress, endurance and scalability testing, each examining different characteristics of system behaviour under demanding conditions. Security testing looks for weaknesses that could allow confidentiality, integrity or availability to be compromised.

Compatibility testing examines behaviour across supported browsers, operating systems, devices, databases or dependency versions. Accessibility testing evaluates whether people with relevant disabilities can use the software effectively and whether applicable accessibility requirements are met. These categories can overlap and are often combined within broader test strategies.

Tests may be manual or automated. Manual testing involves a person directly executing scenarios, inspecting behaviour and recording observations, and it can be valuable for exploratory testing, usability assessment and situations where human judgement is important. Automated tests encode repeatable checks in software so they can be executed consistently, often as part of a continuous integration pipeline. Automation is particularly useful for regression testing because the same checks can run after many changes.

However, automated tests also require maintenance and can themselves contain incorrect assumptions. A large collection of automated tests does not automatically indicate high quality if the tests exercise the wrong behaviour, use weak assertions or fail to cover important cases. Effective testing balances automation with exploratory and human-centred techniques appropriate to the system's risks and requirements.

Testing approaches are often described as black-box, white-box or grey-box depending on how much internal implementation knowledge the tester uses. Black-box testing focuses on externally observable behaviour without relying on source-code structure. White-box testing uses knowledge of internal implementation to guide test design, such as exercising branches, paths or particular data flows. Grey-box approaches use some internal knowledge while still evaluating behaviour through external interfaces.

Structural coverage measures such as statement, branch and condition coverage can provide useful information about which parts of an implementation have been exercised, but coverage is not equivalent to correctness. A test suite can execute every statement while failing to check whether the results are correct. Coverage metrics are therefore indicators of test execution, not complete measures of software quality.

Good testing requires test oracles, which provide a basis for determining whether observed behaviour is correct. An oracle may be an explicit expected output, a mathematical formula, a specification, a database invariant, a reference implementation or a property that must always hold. Some systems make exact expected outputs difficult to calculate, particularly for complex algorithms, stochastic systems or machine-learning applications. In such cases, property-based testing, metamorphic testing, differential testing or statistical evaluation can provide useful alternatives. Boundary cases are particularly valuable because defects often arise at transitions between valid and invalid states. Empty input, minimum and maximum values, malformed data, duplicate values, missing dependencies, repeated operations and unusual sequences should be considered where relevant to the system's requirements.

Testing is closely related to verification and validation but is not identical to either concept. Verification asks whether a product is being built according to specified requirements and can include reviews, static analysis, formal reasoning and testing. Validation asks whether the resulting product meets its intended purpose and user needs. Testing provides evidence relevant to both, but it cannot by itself answer every verification or validation question. Regression testing specifically checks that previously working behaviour remains correct after changes.

Smoke or build-verification testing performs a relatively small set of checks to determine whether a build is sufficiently functional for further testing. Exploratory testing combines learning, test design and execution rather than relying entirely on prewritten scripts. These terms describe different testing objectives and practices rather than mutually exclusive categories.

Software testing has important limitations. Testing can demonstrate that particular tested scenarios produced expected results, but it generally cannot establish that every possible input, execution path, environmental condition and interaction will behave correctly. Complex systems have enormous state spaces, and concurrency, distributed timing, external dependencies and unpredictable users make exhaustive testing impractical. Tests can also be defective, incomplete, brittle or overly coupled to implementation details.

Effective quality engineering therefore combines testing with requirements analysis, design review, static analysis, type systems, code review, monitoring, incident analysis and other preventive or detective controls. The practical objective is to obtain sufficient evidence about software behaviour relative to its risks and requirements, while continuously improving the test suite as new defects, use cases and system changes reveal additional conditions that need to be checked.