5. Test Analysis and Design TechniquesIntroduction and ContextSoftware testing is not merely the execution of test cases after implementation. It is an analytical activity in which testers study requirements, models, code, data, interfaces, and user behaviour to determine what should be tested and how tests can reveal meaningful failures. Test analysis transforms available information into test conditions; test design then converts those conditions into test cases, test data, scripts, or exploratory missions. A test suite cannot normally examine every possible input, execution path, data combination, device, user action, or system state. The central challenge is therefore selection: which tests are most likely to expose important defects at acceptable cost? Test analysis and design techniques provide systematic answers to this question. Some techniques are specification-based, such as equivalence partitioning and decision-table testing. Others are structure-based, such as control-flow coverage and data-flow analysis. Experience-based techniques, including exploratory testing and error guessing, complement formal methods by addressing risks that models may not capture. These techniques are particularly important in full-stack development. A defect may arise in a browser form, an API contract, a validation rule, a database transaction, a background job, or an integration between services. Effective test design connects business rules with technical structures and user scenarios. The techniques in this chapter should therefore be treated as complementary rather than competing alternatives. Learning ObjectivesAfter studying this chapter, you should be able to: 1. Explain the purpose and appropriate use of major test analysis and design techniques. 2. Apply equivalence partitioning and boundary-value analysis to derive efficient test data. 3. Construct and interpret decision tables, state-transition models, use cases, and scenarios. 4. Use pairwise testing to manage combinations of interacting parameters. 5. Conduct exploratory testing and apply error guessing responsibly. 6. Explain control-flow coverage, data-flow analysis, and mutation testing. 7. Select techniques according to risk, requirements, architecture, and available evidence. 8. Evaluate limitations, coverage gaps, and professional responsibilities in test design. Test Analysis as a Selection ProblemTest analysis begins with a test basis: requirements, user stories, acceptance criteria, business rules, architecture, designs, source code, logs, regulatory obligations, and previous defect information. From this basis, the tester identifies test conditions. A test condition may be a feature, rule, input class, state transition, interaction, data definition-use pair, or execution path. Test design determines the inputs, preconditions, actions, expected results, and postconditions needed to evaluate those conditions. A useful test case is not simply a collection of steps. It expresses an observable relationship between an action and an expected outcome. Expected results may include visible responses, database changes, messages, events, audit records, security decisions, performance thresholds, or API status codes. Test techniques can be viewed through three perspectives: - Specification-based techniques derive tests from what the system should do, without requiring knowledge of its internal code.
- Structure-based techniques derive tests from implementation structures such as statements, branches, control-flow paths, and variable usage.
- Experience-based techniques use tester knowledge, intuition, defect patterns, and investigation to discover risks not fully represented in specifications or code models.
A mature test strategy combines these perspectives. Specification-based tests may demonstrate that requirements are addressed, while structure-based tests reveal unexecuted logic. Experience-based testing may discover ambiguous workflows, misleading messages, or unexpected interactions. Equivalence Partitioning and Boundary-Value AnalysisEquivalence PartitioningEquivalence partitioning divides input or output values into groups that the system is expected to process in the same way. The assumption is that testing one representative from a well-defined partition may provide reasonable evidence about the other members of that partition. Partitions should include both valid and invalid classes. Suppose an online loan application accepts an applicant age from 21 through 60 inclusive. Possible partitions are: - age below 21: invalid;
- age from 21 to 60: valid;
- age above 60: invalid;
- non-numeric, blank, or malformed input: invalid, if such values can reach the interface or service.
Representative tests might use 18, 35, 65, blank, and “thirty”. The technique reduces a potentially unlimited input domain to a manageable set, but the partitions must be based on behaviour rather than superficial data types. For example, a discount field may have different behaviour for zero, positive values, negative values, excessive values, and values with excessive decimal precision. Partitioning is also applicable to outputs, file sizes, user roles, transaction statuses, browser types, and API responses. A partition should be revised whenever different values within it trigger different rules. Poorly chosen partitions are a common source of false confidence. Boundary-Value AnalysisDefects frequently occur at the edges of permitted ranges because developers may use incorrect comparison operators, misunderstand inclusive limits, or mishandle transitions between data types. Boundary-value analysis therefore concentrates on values at and around boundaries. For the age range 21–60, typical boundary values are 20, 21, 22, 59, 60, and 61. If the system accepts a file size of at most 10 MB, tests should consider just below the limit, exactly at the limit, and just above it. For a string length of 8–20 characters, test lengths 7, 8, 9, 19, 20, and 21, as well as empty input where relevant. Boundary analysis should consider more than numeric limits. Important boundaries include: - date and time changes, including month-end, leap days, daylight-saving transitions, and time-zone differences;
- pagination limits, such as the first and last page;
- collection sizes, including zero, one, maximum, and maximum plus one;
- authentication attempts before and after lockout;
- monetary precision and rounding thresholds;
- transitions between workflow statuses.
Boundary tests are most effective when combined with equivalence partitions. Partitioning identifies the regions; boundary analysis focuses attention on their edges. Decision Tables for Business RulesA decision table represents combinations of conditions and the actions that should result. It is especially useful when several business rules interact and simple individual tests would not reveal contradictory or missing combinations. Consider a subscription renewal rule with two conditions: payment valid or invalid, and account active or suspended. The actions might be renew subscription, reject payment, or require account review. A decision table lists condition combinations as columns and expected actions beneath them. Each column is a rule. The table should identify impossible combinations, overlapping rules, and combinations for which no expected behaviour has been specified. A practical construction process is: 1. List the relevant conditions. 2. Identify meaningful values for each condition. 3. Calculate or enumerate combinations. 4. Mark combinations that are impossible or irrelevant. 5. Specify the expected action for every applicable rule. 6. Remove duplicated rules only when their outcomes are identical and the distinction is genuinely unnecessary. 7. Derive at least one test case for each significant rule. Decision tables expose omissions particularly well. If a requirement describes what happens when payment is valid and the account is active but says nothing about valid payment for a suspended account, the gap becomes visible. For complex tables, risk-based prioritisation may be necessary, but omitted rules should be resolved rather than silently ignored. State-Transition TestingState-transition testing models a system as a set of states, events, guards, and transitions. A state describes a condition in which the system behaves in a particular way; an event causes or requests a transition; a guard determines whether the transition is permitted; and an action may occur during the transition. An order-management service, for example, may use states such as Created, Paid, Packed, Shipped, Delivered, Cancelled, and Returned. A payment-success event may move an order from Created to Paid. A cancellation request may be allowed from Created but not from Shipped. Tests should examine valid transitions, invalid transitions, repeated events, and sequences of events. Useful coverage goals include: - every state is visited;
- every valid transition is exercised;
- invalid transitions are attempted and correctly rejected;
- important transition sequences are tested;
- guards and actions are verified;
- persistence is checked after a transition.
State models are valuable for login lockouts, workflow approvals, carts, bookings, asynchronous jobs, and device connectivity. They also reveal defects caused by lost events, duplicate messages, race conditions, and incorrect recovery after failure. Use-Case and Scenario TestingUse-case testing derives tests from interactions between an actor and the system to achieve a goal. A complete use case normally includes preconditions, a trigger, the main success flow, alternate flows, exception flows, and postconditions. Scenario testing turns these flows into concrete sequences with specified data and outcomes. For an online purchase, the main flow might include selecting products, entering delivery information, authorising payment, creating an order, and displaying confirmation. Alternate scenarios may involve an out-of-stock product, an expired card, a changed price, a lost network connection, or a duplicate submission. The tester should not treat the successful path as the whole requirement. Exception and recovery behaviour often carries greater operational risk. Use-case tests are particularly helpful for acceptance testing and system integration testing because they reflect user goals across multiple components. They should nevertheless be supported by lower-level tests. A scenario can show that a complete transaction works without proving that every validation rule, branch, or data condition has been exercised. Pairwise and Combinatorial TestingMany systems accept multiple parameters: browser, operating system, language, payment method, user role, network type, and device size. Exhaustively testing every combination may be infeasible. Pairwise testing selects combinations so that every relevant pair of parameter values appears in at least one test. For example, a web application may be tested across three browsers, two operating systems, and three payment methods. Rather than executing all 18 combinations, a pairwise design may use fewer tests while ensuring interaction coverage for each pair of values. The reduction is useful because many defects are caused by interactions between two factors. Pairwise testing is not a guarantee against higher-order interaction defects. If a failure occurs only when three or more specific values coincide, pairwise tests may miss it. The strength of the design should therefore be increased for high-risk features, and constraints must be encoded. For example, a particular payment method may not be supported on a particular platform. Invalid combinations should not be generated as though they were meaningful tests. Combinatorial tools can generate covering arrays, but the tester remains responsible for selecting parameters, values, constraints, and expected results. Automation reduces enumeration effort; it does not replace analysis. Exploratory Testing and Error GuessingExploratory testing is a structured learning activity in which test design, execution, and interpretation occur together. Rather than following a completely predetermined script, the tester investigates the product, forms hypotheses, and adapts subsequent tests according to observed evidence. Exploratory testing is not random clicking. It requires a mission, a time limit or session boundary, relevant notes, and a clear method for reporting findings. A session might investigate “account recovery under interrupted network conditions” for 60 minutes. The tester may vary input data, interrupt requests, revisit pages, inspect notifications, and compare behaviour across devices. Observations can lead to new test ideas that were not apparent before execution. Error guessing uses knowledge of common failure modes to devise targeted tests. Examples include submitting a form twice, refreshing after payment, using a very long string, entering whitespace, changing system time, navigating with the browser Back button, uploading a renamed file, or repeating an expired link. Error guessing is powerful when informed by defect history, technology risks, and domain experience, but it is difficult to measure and may reflect individual bias. It should supplement, not replace, systematic techniques. Control-Flow CoverageControl-flow testing represents program execution as a graph of nodes and edges. Nodes may represent statements or blocks; edges represent possible transfers of control. Tests are then assessed according to which structural elements they execute. Important measures include: - Statement coverage: the proportion of executable statements run by tests.
- Branch or decision coverage: the proportion of decision outcomes, such as true and false branches, exercised.
- Condition coverage: whether individual Boolean conditions take both relevant outcomes.
- Path coverage: whether selected execution paths are exercised.
Coverage is evidence about exercised structure, not proof that the software is correct. A test suite can obtain high statement coverage while failing to check meaningful expected results. Branch coverage may still miss combinations of conditions, and complete path coverage is often impractical because loops and combinations create a very large or infinite number of paths. A disciplined approach identifies unexecuted branches, determines whether they are reachable, and either adds tests or documents justified exclusions. Coverage thresholds should be interpreted with risk and code criticality rather than pursued as arbitrary targets. Tests that merely execute code without meaningful assertions provide weak assurance. Data-Flow AnalysisData-flow testing follows how variables and data items are defined, used, modified, and destroyed. A definition occurs when a value is assigned; a use occurs when the value influences a computation or a decision. A definition-use pair connects a definition to a reachable use without an intervening redefinition. Consider a variable `total` assigned from a cart calculation, used in a discount decision, and later reassigned from a database response. Tests should examine whether the original definition reaches the intended uses, whether an uninitialised value can be used, and whether a value is overwritten before it is consumed. Data-flow anomalies include defining a variable and never using it, using it before definition, and redefining it without an intervening use. Data-flow analysis is valuable for financial calculations, security permissions, session tokens, and data transformations across service boundaries. Static-analysis tools can identify some anomalies automatically, while dynamic data-flow coverage records which definitions and uses were exercised. The method requires careful interpretation because aliases, objects, concurrency, and framework behaviour can complicate the analysis. Mutation TestingMutation testing evaluates the fault-detection ability of a test suite by creating small syntactic changes, called mutants, in the program. Examples include replacing `>` with `>=`, changing an arithmetic operator, negating a Boolean condition, deleting a statement, or altering a constant. If existing tests fail, the mutant is said to be killed. If tests pass, the mutant survives and may indicate a missing test or weak assertion. The mutation score is commonly expressed as the proportion of non-equivalent mutants killed. Equivalent mutants produce behaviour indistinguishable from the original for all relevant inputs and cannot be killed by a valid test; identifying them may require analysis. Mutation testing can be computationally expensive, particularly in large systems, so teams often apply it to critical modules or representative test sets. Mutation testing is not a replacement for requirements-based testing. A suite can kill many artificial mutants while omitting an important business rule that was never represented in the mutations. Its principal value is assessing test sensitivity: do the tests detect realistic small changes in implementation? Selecting and Combining TechniquesTechnique selection should reflect the test basis, product risk, architecture, and test level. A registration form may benefit from equivalence partitions and boundary values. A pricing engine may require decision tables, data-flow analysis, and mutation testing. A workflow service calls for state-transition and scenario testing. A multi-platform user interface may require pairwise testing. Unfamiliar or rapidly changing features are strong candidates for exploratory testing. A useful risk-based sequence is to identify failure consequences, determine the relevant model, select a primary technique, and add complementary techniques for blind spots. For example, an order cancellation feature can be analysed using a state model, boundary tests for cancellation timing, a decision table for refund rules, and exploratory tests for duplicate requests. Automation should be applied where repetition is high and expected results are stable; exploratory and usability-oriented work may require human judgement. Traceability is important at postgraduate and professional levels. Test conditions should be linked to requirements, risks, code components, defects, and evidence. Metrics should be interpreted carefully. Test count, coverage percentage, mutation score, and defect discovery rate are indicators, not direct measures of quality. A small number of high-value tests may provide more assurance than a large number of redundant tests. Illustrative Case Study: Testing a Digital Wallet Transfer ServiceBackgroundThe following fictional case illustrates how several techniques can be combined. A digital wallet allows a verified user to transfer money to another user. The service includes a web client, REST API, fraud checks, a ledger database, notifications, and an asynchronous settlement worker. Situation and ProblemEarly system testing found that normal transfers succeeded, but failures were reported when users submitted the transfer twice, when the balance was exactly equal to the transfer amount, and when a fraud review returned after a timeout. The team needed a compact but defensible test design before release. AnalysisThe analysts first created equivalence partitions for amount: zero or negative, valid positive amount within limits, above the transaction limit, excessive precision, malformed, and blank. Boundary analysis added values just below, at, and just above the minimum, maximum, and available balance. A decision table combined verified status, sufficient balance, fraud result, and recipient validity. It specified whether the transfer should be rejected, placed under review, completed, or retried. A state model represented Requested, Pending Review, Approved, Settled, Rejected, and Reversed. Duplicate requests and timeout responses were treated as events requiring explicit tests. The team then designed use-case scenarios for a successful transfer, insufficient funds, a blocked recipient, an interrupted connection, and a repeated submission. Pairwise testing covered browser, device type, currency, and notification channel, subject to product constraints. Exploratory sessions focused on refreshing the confirmation page, replaying API requests, changing the client clock, and observing recovery after worker failure. At code level, branch coverage revealed an untested fraud-review timeout branch. Data-flow analysis showed that a transaction identifier could be regenerated during retry, risking duplicate ledger entries. Mutation testing changed the balance comparison from `>=` to `>`; the existing tests failed to detect the mutant, demonstrating that the exact-balance boundary was missing. Approach and OutcomeThe team added tests for exact balance, idempotency keys, repeated messages, delayed fraud decisions, and recovery after a worker restart. It also strengthened assertions to verify ledger uniqueness, final state, notification content, and audit records rather than merely checking an HTTP success response. The resulting suite was smaller than an exhaustive combination of all parameters but covered the principal partitions, boundaries, rules, states, and high-risk interactions. Learning PointsThe case demonstrates that no single technique would have been sufficient. Boundary analysis exposed the comparison defect; state testing addressed asynchronous lifecycle behaviour; decision tables clarified business rules; data-flow analysis identified an identifier risk; and mutation testing assessed whether the tests were sensitive to a realistic implementation change. The techniques provided different views of the same system and produced stronger assurance when combined. Challenges, Limitations, and Common MistakesSeveral errors recur in test design. Testers may create partitions without checking whether all values truly have equivalent behaviour. They may test only nominal boundaries, omit invalid transitions, or treat a decision table as complete without validating its rules with domain experts. Pairwise designs may ignore parameter constraints. Exploratory testing may become undocumented ad hoc execution. Structural coverage may be pursued as a target while assertions remain weak. Other limitations arise from system complexity. Models may become stale as requirements change. State combinations may grow rapidly. Asynchronous and distributed systems can produce nondeterministic results. Mutation testing can consume substantial computing time and may generate equivalent mutants. Automated coverage tools may not recognise behaviour implemented through reflection, generated code, or external services. These limitations do not invalidate the techniques. They require judgement, review, prioritisation, and transparent reporting. Test evidence should distinguish tested behaviour, untested behaviour, infeasible paths, assumptions, and residual risk. Professional, Ethical, and Governance ConsiderationsTesters have a professional responsibility to report evidence accurately. Coverage percentages must not be presented as guarantees, and known limitations should not be concealed to meet a release target. Test data must protect personal, financial, health, and authentication information. Production data should be masked or replaced where possible, and test environments should be access-controlled. For regulated or safety-relevant systems, test conditions, expected results, approvals, tool versions, and execution evidence may need to be retained for audit. Automated generation does not remove accountability: a tester or technical lead must review generated tests, constraints, and oracle logic. AI-assisted test generation can propose partitions, scenarios, and mutations, but it may reproduce biased assumptions, overlook domain rules, or produce tests that assert implementation rather than intended behaviour. Human review and traceability remain essential. Emerging PracticeModern teams increasingly integrate test design with continuous integration, contract testing, service virtualisation, property-based testing, and observability. Property-based tools generate many inputs from stated properties and can extend equivalence and boundary analysis. Code-coverage and mutation results can be reported continuously for changed components. AI-based tools may assist with requirement classification, scenario generation, test-data synthesis, and defect-pattern analysis, although their outputs require validation. The emerging direction is not the replacement of testers by automation. It is the development of connected quality intelligence: requirements, risks, code changes, production incidents, logs, and test evidence inform one another. Such integration is useful only when teams preserve meaningful oracles, explainable decisions, privacy controls, and human responsibility. Best Practices for Test Analysis and Design1. Start with risks and observable behaviour, not with a preferred tool. 2. Identify valid and invalid partitions and examine every significant boundary. 3. Use decision tables for interacting business rules and state models for lifecycle behaviour. 4. Include alternate, exception, retry, cancellation, and recovery scenarios. 5. Apply pairwise testing only after identifying constraints and high-risk higher-order interactions. 6. Combine specification-based, structure-based, and experience-based techniques. 7. Use coverage and mutation results diagnostically rather than as isolated targets. 8. Make expected results precise, including data, events, logs, security outcomes, and side effects. 9. Maintain traceability and document exclusions, assumptions, and residual risk. 10. Review test designs with developers, domain specialists, security professionals, and operations personnel where appropriate. Chapter SummaryTest analysis and design techniques provide disciplined ways to select effective tests from large and complex possibility spaces. Equivalence partitioning reduces input domains into behaviourally meaningful classes, while boundary-value analysis focuses on likely edge defects. Decision tables model combinations of business conditions, and state-transition testing examines lifecycle behaviour, valid transitions, and invalid events. Use-case and scenario testing represent user goals and exception flows. Pairwise testing manages combinations of parameters, while exploratory testing and error guessing use investigation and experience to expose less predictable risks. Control-flow coverage, data-flow analysis, and mutation testing examine implementation structure and the strength of the test suite itself. Each technique has blind spots, so professional practice combines methods according to risk, test level, architecture, and available evidence. Accurate reporting, privacy, traceability, governance, and human review remain essential, especially when automation and AI are used. Effective test design is therefore both a technical discipline and a professional judgement activity. Key TermsEquivalence partitioning: Division of inputs or outputs into classes expected to exhibit similar behaviour. Boundary-value analysis: Testing values at, just below, and just above significant limits. Decision table: A tabular representation of condition combinations and their resulting actions. State transition: A change from one system state to another caused by an event, subject to conditions. Use case: A description of an actor’s interaction with a system to achieve a goal. Scenario: A concrete sequence of actions, data, and expected outcomes representing a flow. Pairwise testing: Combinatorial testing in which every relevant pair of parameter values is covered. Exploratory testing: Testing in which learning, test design, and execution occur concurrently. Error guessing: Experience-based creation of tests aimed at likely failure modes. Control-flow graph: A representation of program blocks and possible transfers of execution. Statement coverage: The proportion of executable statements executed by a test suite. Branch coverage: The proportion of decision outcomes exercised by tests. Condition coverage: Coverage of individual Boolean condition outcomes. Data-flow analysis: Examination of where data is defined, used, modified, and destroyed. Definition-use pair: A path linking a data definition to a subsequent use without redefinition. Mutation testing: Evaluation of test effectiveness using deliberately modified program versions. Mutant: A modified version of a program created for mutation testing. Mutation score: The proportion of non-equivalent mutants detected by the test suite. Test oracle: A mechanism or rule used to determine whether an observed result is correct. Traceability: The ability to link requirements, risks, tests, code, defects, and evidence. Review QuestionsShort Answer Questions1. What is the difference between a test condition and a test case? 2. Why should equivalence partitions include invalid classes? 3. What is the purpose of a decision table? 4. Define branch coverage. 5. What does it mean for a mutant to survive? Long Answer Questions1. Explain equivalence partitioning and boundary-value analysis using a suitable web-application example. 2. Describe how a state-transition model can be used to test an asynchronous order workflow. 3. Explain the construction and value of decision tables for complex business rules. 4. Compare specification-based, structure-based, and experience-based test techniques. 5. Discuss the benefits and limitations of mutation testing and structural coverage. Analytical / Application Questions1. A booking system accepts dates from one day ahead to 180 days ahead, allows cancellation only before check-in, and charges different fees according to membership status. Design suitable partitions, boundary tests, and a decision-table structure. 2. A payment API may receive duplicate requests because clients retry after timeouts. Design a combined state-transition, scenario, and exploratory testing approach. 3. A test suite has 95% statement coverage but does not kill a mutant that changes an inclusive balance comparison to an exclusive comparison. Analyse what this indicates and propose additional tests. 22. Multiple Choice Questions with AnswersQuestion 1Which test set best represents boundary-value analysis for an inclusive valid range of 10 to 20? A. 10, 15, 20 B. 9, 10, 11, 19, 20, 21 C. 1, 5, 10, 15, 20 D. 0, 10, 20, 30 Correct Answer: B. 9, 10, 11, 19, 20, 21 Question 2What is the principal purpose of a decision table? A. To measure executable statement coverage B. To model variable definitions and uses C. To represent combinations of conditions and expected actions D. To generate browser compatibility combinations Correct Answer: C. To represent combinations of conditions and expected actions Question 3Which technique is most directly concerned with valid and invalid lifecycle changes? A. State-transition testing B. Mutation testing C. Pairwise testing D. Equivalence partitioning Correct Answer: A. State-transition testing Question 4A pairwise test design guarantees that: A. Every possible combination of all parameters is tested B. Every pair of selected parameter values occurs in at least one test C. Every program path is executed D. Every business rule is automatically validated Correct Answer: B. Every pair of selected parameter values occurs in at least one test Question 5Which statement best describes exploratory testing? A. It is random execution without documentation B. It uses only automated scripts created before execution C. Test design, execution, and learning occur together within a structured investigation D. It is limited to tests derived from source-code branches Correct Answer: C. Test design, execution, and learning occur together within a structured investigation Question 6A test suite executes every statement but misses the false outcome of an important decision. Which measure is most clearly insufficient? A. Statement coverage B. Branch coverage C. Pairwise coverage D. Mutation score Correct Answer: A. Statement coverage Question 7In data-flow analysis, a definition-use pair connects: A. A requirement to a test case B. A program state to an invalid transition C. A data assignment to a subsequent use without intervening redefinition D. Two browser and operating-system combinations Correct Answer: C. A data assignment to a subsequent use without intervening redefinition Question 8What does a surviving mutant usually suggest? A. The original program definitely contains a defect B. The test suite may lack sensitivity to a realistic implementation change C. The mutant is always equivalent to the original program D. Statement coverage must be exactly zero Correct Answer: B. The test suite may lack sensitivity to a realistic implementation change Question 9Which technique is most appropriate for reducing tests across browsers, operating systems, and payment methods while covering interactions between pairs? A. Pairwise testing B. State-transition testing C. Error guessing D. Data-flow analysis Correct Answer: A. Pairwise testing Question 10In the digital-wallet case, why was an exact-balance test important? A. It tested a transition between browser states B. It exposed the difference between inclusive and exclusive balance comparisons C. It guaranteed complete path coverage D. It eliminated the need for decision tables Correct Answer: B. It exposed the difference between inclusive and exclusive balance comparisons
|