Software Testing and Configuration Management

This chapter closes Unit 6 with verification and validation, the vocabulary that distinguishes an error from a fault from a failure, the two structural testing families (white-box and black-box) and their specific techniques, the testing-level hierarchy from unit to acceptance, and software configuration management — change control, reuse, re-engineering and reverse engineering.

Verification and Validation; Error, Fault, Bug and Failure

Verification versus validation, and the error/fault/failure chain
TermMeaning
Verification'Are we building the product RIGHT?' — checking that each work product correctly implements the specification/design that preceded it.
Validation'Are we building the RIGHT product?' — checking that the finished system actually satisfies the customer's real needs, not just a formal specification.
ErrorA human mistake made while developing the software (a misunderstanding, a typo in logic).
Fault (bug)The resulting incorrect step, process or data definition actually left in the code/artefact — the concrete manifestation of the error.
FailureThe observable, external deviation from expected behaviour when the fault is actually TRIGGERED during execution — a fault can sit dormant and never cause a failure if the faulty code path is never exercised.

White-Box and Black-Box Testing

  • White-box (structural/glass-box) testing designs test cases from knowledge of the code's INTERNAL structure and logic. BASIS PATH TESTING derives a set of independent execution paths from the code's control-flow graph, using CYCLOMATIC COMPLEXITY (V(G) = edges − nodes + 2, for a single connected graph) to determine the minimum number of independent paths needed for full coverage. CONTROL STRUCTURE TESTING further specialises into condition testing (exercising each individual boolean sub-condition), data-flow testing (exercising paths from a variable's definition to its use) and loop testing (exercising a loop zero times, once, and many times, plus its boundary counts).
  • Black-box (behavioural/functional) testing designs test cases from the SPECIFICATION alone, with no reference to the code's internals — DERIVING TEST CASES via techniques like equivalence partitioning (dividing inputs into classes expected to be handled alike, testing one representative per class rather than every value) and boundary-value analysis (testing values exactly at, just above and just below a boundary, where defects cluster most). ALPHA testing is conducted by end-users AT THE DEVELOPER's site under the developer's observation; BETA testing is conducted by end-users AT THEIR OWN site with no developer present, exposing the software to real-world conditions and usage patterns the developer's own test environment cannot replicate.
⚠️ 100% statement coverage is not 100% branch/path coverage
A test suite can execute every LINE of code at least once (100% statement coverage) while still never exercising one branch of an if-else (if, say, the else branch's single line happens to also be reachable and covered by a different path) OR, more commonly, without ever testing the FALSE outcome of a condition that never separately branches to a distinct uncovered line. Basis path testing, built on the control-flow graph rather than raw line counts, is designed specifically to guarantee a stronger, path-based notion of coverage that a naive line-counting metric can miss entirely.

Unit, Integration, Regression, Performance and Stress Testing

  • Unit testing verifies the smallest testable piece (a function/method/class) in isolation, typically with stubs/mocks standing in for its collaborators; integration testing verifies that units combine and interact correctly when assembled — the classic bug this catches is a mismatch at an INTERFACE between two units that each individually pass their own unit tests perfectly.
  • Regression testing re-runs previously-passing tests after a change, to catch a NEW defect the change may have introduced into functionality that used to work correctly — this is exactly why a good regression suite is run on every change, not just once at the very end.
  • Performance testing measures response time/throughput under EXPECTED load; stress testing deliberately pushes the system BEYOND its expected/normal operating limits (extreme load, reduced resources) to discover how and where it breaks and whether it fails gracefully — the two ask different questions (how well does it perform, versus how does it fail) rather than being the same test at two intensities.

Software Configuration Management: Change Control, Reuse and Re-engineering

Software Configuration Management (SCM) tracks and controls changes to a project's evolving artefacts (requirements, design, code, tests, documentation) over its whole lifecycle — a CONFIGURATION ITEM is any such artefact placed under version control; a BASELINE is a formally reviewed and agreed configuration that can only change through a formal CHANGE CONTROL procedure thereafter (a change request, impact analysis, approval, then implementation and re-baselining) — this discipline is what prevents 'which version is actually deployed' from becoming an unanswerable question on a project with many contributors.

  • Software reuse builds new systems partly or wholly from existing, proven components rather than writing everything anew — reducing cost and risk when a suitable component already exists (the same underlying idea as component-based development from this unit's process-models section).
  • Software re-engineering examines and alters an EXISTING legacy system to improve its structure/maintainability WITHOUT changing its external behaviour — it is a renovation, not a rewrite, and it typically proceeds through REVERSE ENGINEERING first: analysing existing code (which may have poor or no documentation) to recover a higher-level design/specification understanding, which is then used to guide the re-engineering (forward engineering back into an improved implementation).

Key takeaways

  • Verification asks 'right product built correctly?'; validation asks 'right product built at all?' — different questions, both needed.
  • An error (human mistake) leaves a fault (bug) in the artefact, which causes a failure only when actually triggered during execution.
  • White-box testing (basis path, condition, data-flow, loop testing) uses code internals; black-box testing (equivalence partitioning, boundary-value analysis, alpha/beta testing) uses only the specification.
  • Regression testing re-checks previously-working functionality after a change; performance and stress testing ask different questions (how well versus how it fails).
  • Re-engineering improves an existing system's structure without changing external behaviour, typically via reverse engineering first; a baseline changes only through formal change control.

Practice questions (8)

Attempt each one before opening the answer. Every explanation names the tempting wrong option as well as the right one, because that is where marks are lost.

  1. Validation, as distinct from verification, asks:

    1. 'Are we building the right product?' — does it satisfy the customer's real needs
    2. 'Are we building the product right?' — does each artefact match its own specification
    3. Nothing; validation and verification are identical
    4. Only whether the code compiles
    Show answer

    Answer: A — 'Are we building the right product?' — does it satisfy the customer's real needs

    Verification checks conformance to a preceding specification; validation checks the finished product against the customer's actual, real-world needs, which the specification might itself have gotten wrong.
  2. A fault (bug) present in the code that is never actually triggered during execution:

    1. Produces no failure, since a failure requires the fault to actually be exercised
    2. Always produces a failure regardless
    3. Is the same thing as a human error
    4. Cannot exist in any real program
    Show answer

    Answer: A — Produces no failure, since a failure requires the fault to actually be exercised

    A failure is the observable consequence of a fault being triggered during execution; a dormant fault on a code path that is never exercised produces no visible failure at all, however incorrect the code itself is.
  3. Cyclomatic complexity, used in basis path testing, is computed (for a single connected control-flow graph) as:

    1. Edges − Nodes + 2
    2. Edges + Nodes
    3. Nodes − Edges
    4. Always exactly 1 regardless of the graph
    Show answer

    Answer: A — Edges − Nodes + 2

    V(G) = E − N + 2 gives the number of independent linear paths through the control-flow graph, which is the minimum number of test cases needed for basis path coverage.
  4. Boundary-value analysis, a black-box testing technique, is motivated by the observation that:

    1. Defects cluster most often around the edges of an input's valid range
    2. Every input value is equally likely to reveal a defect
    3. It requires access to the source code's internal structure
    4. It only tests values well inside the middle of the valid range
    Show answer

    Answer: A — Defects cluster most often around the edges of an input's valid range

    Off-by-one errors and other boundary mistakes are among the most common defects, so testing values exactly at, just below and just above a boundary finds problems far more efficiently than testing arbitrary interior values.
  5. Beta testing, compared to alpha testing, is conducted:

    1. By end-users at their own site, with no developer present
    2. By developers only, before any code is written
    3. At the developer's own site, under the developer's observation
    4. Only on hardware, never on software
    Show answer

    Answer: A — By end-users at their own site, with no developer present

    Alpha testing happens at the developer's site under observation; beta testing happens at the end-user's own site with no developer present, exposing the software to real-world conditions the developer's environment cannot replicate.
  6. Which of the following are true of software re-engineering? (More than one option may be correct.)

    1. It improves an existing system's internal structure without changing its external behaviour
    2. It typically proceeds through reverse engineering first, to recover a higher-level understanding of legacy code
    3. It always means rewriting the system entirely from scratch
    4. It is applied to an existing legacy system, not to a brand-new project
    Show answer

    Answer: A — It improves an existing system's internal structure without changing its external behaviour; B — It typically proceeds through reverse engineering first, to recover a higher-level understanding of legacy code; D — It is applied to an existing legacy system, not to a brand-new project

    Re-engineering is a renovation of an existing system, typically starting with reverse engineering to recover understanding of poorly-documented legacy code, and specifically preserves external behaviour while improving internal structure — it is not a rewrite from scratch.
  7. Name the type of testing that re-runs previously-passing tests after a change, specifically to catch a new defect the change may have introduced into functionality that used to work correctly.

    Numerical answer — type the value.

    Show answer

    Answer: regression testing

    Regression testing exists precisely to guard against a change silently breaking functionality that was previously working, which is why it is re-run on every change rather than performed once.
  8. A baseline in software configuration management can only be changed thereafter through:

    1. A formal change control procedure (request, impact analysis, approval, implementation, re-baselining)
    2. Any developer editing it directly with no review
    3. It can never be changed under any circumstances
    4. Deleting the entire project and starting over
    Show answer

    Answer: A — A formal change control procedure (request, impact analysis, approval, implementation, re-baselining)

    A baseline is a formally reviewed and agreed configuration, and this discipline is exactly what keeps 'which version is actually deployed' from becoming an unanswerable question on a project with many contributors.