1Verification
Ensuring the product meets its specified requirements. Asks: 'Are we building the product right?'
2Validation
Demonstrating the product meets its intended use when placed in the intended environment. Asks: 'Are we building the right product?'
3Brooks's rule of thumb for scheduling effort
1/3 planning, 1/6 coding, 1/4 component test and early system test, 1/4 system test with all components in hand (testing is about half the work)
4Where bugs come from (approximate percentages)
Specification ~55%, design ~25%, code ~15%, other ~5%
5Relative cost of fixing a bug
Rises about tenfold per phase: ~\$1 in specification, \$10 in design, \$100 in code, \$1000 once released
6Latent bug
A bug that has not yet been discovered
7When does a software bug occur? (5 rules)
Software doesn't do what the spec says; does what the spec says it shouldn't; does something the spec doesn't mention; doesn't do something it should even though the spec doesn't mention it; or is hard to understand, hard to use, or slow
8Goal of a software tester
Find bugs as early as possible and make sure they get fixed, without chasing unattainable perfection
9Why testers should attend requirement reviews and be suspicious of requirements
Most bugs originate in the specification, and missing requirements can't be caught by testing code later
10Fault (bug)
A condition that causes a system to fail in performing its required function
11Failure
The inability of a system or component to perform a required function according to its specification
12Debugging
The activity by which faults are identified and rectified
13Test case
Inputs to test the program plus the predicted outcomes (according to the specification); a formal procedure where every step is subject to mistakes
14Test suite
A collection of test cases
15Testing oracle
A mechanism (a program, process, or body of data) that helps determine whether the program produced the correct outcome; often a set of input/expected-outcome pairs
16Outcome vs. output
Outcome is what we expect to happen as a result of a test; e.g., the screen not changing is a tangible outcome even though there is no output
17Coincidental correctness
The test gives the expected outcome even though the program performs the wrong computation (e.g., y = x² vs. y = 2x tested with x = 2); so a match doesn't strictly mean the test 'passed'
18Specification (formal definition)
A relation S ⊆ I × O between the input space and the output space; ideally defines intended behavior for every input, in practice only for some
19Program correctness (w.r.t. S)
P is correct iff for each input in S's domain, P halts and returns a value in accordance with the specification
20Central problem of testing
Find input values that reveal all faults (essentially proving the program correct); impossible, since no computable procedure exists (Howden, 1976)
21Realistic goal of testing
Select inputs that increase our confidence that the program is correct
22Functional vs. non-functional requirements
Functional: features the product supports (save, print, spell check). Non-functional: constraints on the product (security, reliability, usability, platform)
23Why random testing matters as a baseline
It gives a lower bound: everything testers do should be better than random testing, though random tests may reveal cases you never thought of
24Expected outcomes are hard to specify because...
You may not know what the outcome should be, the developer may have a misconception, or the output may be too large to analyze; automate comparison when possible
25Reality #1
It is impossible to test a program completely: all inputs, outputs, and paths are huge, and the spec must also be correct and complete
26Reality #2
Software testing is a risk-based exercise: skipping inputs is a risk (financial loss, security, loss of life); too much testing is too costly, too little raises failure probability
27Testing equilibrium
The balance point between the cost of testing (rises with more testing) and the number of missed bugs (falls with more testing)
28Reality #3
Testing cannot show the absence of bugs
29Dijkstra's famous testing quote
'Program testing can be used to show the presence of bugs, but never to show their absence!' (Edsger Dijkstra, 1972 Turing Award)
30Reality #4
The more bugs you find, the more bugs there are: bugs cluster because programmers have bad days, repeat mistakes, and some bugs are the tip of the iceberg
31Reality #5
Test cases lose their effectiveness over time
32Pesticide paradox
Beizer's term: the more you test software, the more immune it becomes to your test cases; remedy is to keep writing new and different tests
33Reality #6
Not all test cases are equal: some are more important, so prioritize them
34Reality #7
Bugs can go undetected for a long time; heavy testing and wide use don't mean all bugs are found
35Reality #8
Not all bugs found will be fixed: it may not really be a bug (spec wrong), too risky to fix, not worth it, or no time
36Reality #9
Specifications are never final: software is a moving target (fierce competition, rapid releases, easy to change), unlike a bridge once construction starts
37Reality #10
Software testing is a disciplined and technical profession (sophisticated techniques, tool support, rewarding careers)
38Undecidable problem
A problem for which no algorithm solves it for all programs and all inputs
39Halting problem
Asks whether a specific program terminates on a given input; undecidable (Turing and Church, 1936)
40Rice's Theorem (1953)
A corollary of the halting problem: predicting almost any non-trivial program behavior is undecidable
41Examples of undecidable problems in testing
Is a statement reachable? Is a path feasible? Will an array index go out of bounds? Are two functions equivalent? Does the program meet its specification?
42Common misconception about the halting problem
That 'programs can't find bugs in other programs'; correct reading: one program cannot perfectly tell you whether a certain bug exists
43The 3 things no bug-finding program can do all at once
(1) Always report a bug when there is one, (2) always report no bug when there isn't one, (3) always give a definitive answer
44Unsound tool
Gives up (1): it misses some bugs but can still find many that exist
45Sound but conservative tool
Gives up (2): it never misses a bug but may warn about bugs that aren't there (plays it safe)
46Tool that gives up giving a definitive answer
It might run forever or run out of memory
47Takeaway on undecidability
Perfect bug-finding is impossible, but good bug-finding is possible
48Control flow graph (CFG)
A static, abstract representation of a program: a directed graph G = (N, E) of statement and predicate nodes with edges showing flow of control
49Statement node (CFG)
Represents a simple statement or a basic block; drawn as a circle
50Predicate node (CFG)
Represents a conditional statement; drawn as a rectangle with T and F edges
51Basic block
A sequence of statements treated as one unit and run one after the other
52CFG for a switch-case
e is not a predicate; draw a chain of predicates e == v1, e == v2, ... then default; without break, a case falls through to the next case's statement
53CFG for a while loop
Predicate at the top; T goes into the body, which loops back to the predicate; F exits the loop
54CFG for a for loop
Initialization node, then predicate (e.g., j <= limit); T goes into body then increment node and back to predicate; F exits
55Path
A unique sequence of nodes (n1, ..., nt) where each consecutive pair is an edge in the graph
56Complete path
A path that starts at the first node and ends at the last node of the graph
57Execution path
A complete path that can be exercised by some input data
58Subpath
A subsequence of a path
59Elementary path
A path in which all nodes are unique
60Simple path
A path in which all edges are unique
61Path condition
The conjunction of the individual predicate conditions at each branch point along a path; the input must satisfy it for the path to execute
62Feasible path
A path that can be exercised by some input data
63Infeasible path
A path that no input can exercise, caused by contradictory predicates (e.g., x < 10 true then x < 20 false)
64Why infeasible paths are a problem
You may hunt for impossible tests; they may signal a control-flow error; future changes may make them feasible and untested; they come in clusters and are common
65Number of paths in if ((A||B) && (C||D))
7 paths once short-circuit is expanded (4 true, 3 false), not 2
66Why loops can give infinitely many paths
If the loop control variable is supplied externally (user input), the number of paths is unbounded
67Testing strategy: divide and conquer
Begin with testing-in-the-small (a module or class) and move toward testing-in-the-large (the whole system)
68Unit testing
Done by each developer; white-box; ensures each module (class, subprogram) is implemented correctly; looks at data structures, boundaries, error-handling paths, interfaces
69Driver (unit testing)
Test code that calls the module under test
70Stub (unit testing)
Test code that stands in for a module the module under test calls
71Why unit testing is often performed poorly
Developers focus on writing code rather than tests, and an automation framework makes execution efficient but doesn't make testing adequate
72Integration testing
Done by a small team in a short time frame; ensures the interfaces between components (which developers couldn't test) are implemented correctly
73Big-bang integration
Integrate everything at once. Pro: whole system available. Cons: components may not all be ready, no component focus, errors harder to locate
74Incremental integration
Integrate piece by piece. Pros: focus on each module, easy to locate errors. Con: needs stubs and/or drivers
75Top-down integration
Top module tested with stubs; stubs replaced one at a time, depth first; a subset of tests re-run as modules are added
76Bottom-up integration
Worker modules grouped into clusters (builds) and integrated; drivers replaced one at a time, depth first
77Sandwich integration
Top modules tested with stubs while worker clusters are integrated from the bottom
78System testing
Done by a separate group; pretend to be end users; black-box; driven by use cases; focus on functionality plus recovery, performance, etc.; needs a System Test Plan
79System test group size guidance
About 30% of the developer count is good (ideal ~5 testers per 10 developers); many companies give only ~25%
80Adequacy criterion for system testing
Requirements coverage, but testers must think beyond the stated requirements
81Alpha testing
Development and main phases done but not ready to release; friendly users exercise the release and report crashes and issues
82Beta testing
Like alpha but the software is nearly ready to release, so fewer issues; more commonly used than alpha
83Acceptance testing
The customer's final check before accepting the software; in practice customers often don't know what to do
84V-Model
Left side shows the reference material (requirements, architectural design, component design, code); right side shows the matching testing phase (acceptance, system, integration, unit)
85Testing phases vs. types of testing
A phase says when and at what scope you test (unit, integration, system); a type says what concern you test (performance, security, etc.)
86Functionality testing
Checks that the system does what the specification says
87Performance testing
Tests the run-time performance of the software; start early by checking components against their performance budget
88Stress testing
Executes the system so it demands resources in abnormal quantity, frequency, or volume to see how it handles heavy load
89Longevity / reliability testing
Evaluates behavior over a long period under normal and peak load (without stressing it); estimates failure rate and mean-time-between-failures; finds memory leaks
90Recovery / failover testing
Forces the software to fail in a variety of ways and verifies that recovery is properly performed (e.g., one component slow or erroring)
91Security testing
Verifies that protection mechanisms built into a system will actually protect it from improper penetration
92Usability testing
Identifies discrepancies between a product's user interface and the human engineering requirements of its potential users
93Regression testing
Re-testing modified software to detect whether new faults were introduced into previously tested code
94Regression testing options
Retest-none, retest-all, or selective retesting; can be expensive
95Black-box testing
Uses the specification as the reference for test selection and adequacy (a.k.a. specification-based or functional testing); end-user perspective; criteria not precise; planning can start early
96White-box testing
Uses the source code as the reference for test selection and adequacy (a.k.a. structural or program-based testing); precise criteria; assumes the code fully implements the spec
97White-box vs. black-box: which is better?
Neither; the real difference is how tests are generated and adequacy determined; neither can be exhaustive, so use both
98Equivalence partitioning
Systematically reducing a huge set of possible test cases to a small but effective subset by grouping inputs into equivalence classes
99Property that defines an equivalence partition
Its members test the same thing or reveal the same bugs: if one input is handled correctly (or incorrectly), the others very likely are too
100How to identify equivalence partitions
Identify all input sources, then for each, which groups should be treated differently; group similar inputs, outputs, and operations; it takes judgment and domain expertise
101Equivalence classes for a square root function
Negative numbers, zero, perfect squares, non-perfect squares, decimal numbers, non-numeric input; pick one test per class
102Test-to-pass
Assures the software minimally works using simple, straightforward cases that don't try to break it
103Test-to-fail
Cases designed to break the software and probe common weaknesses
104Boundary value analysis: core idea
Faults cluster near boundaries (off-by-one errors, < vs <=); test 'barely valid' and 'barely invalid' values
105Boundary value testing (basic)
For each variable use min, min+, nominal, max-, max: 4n+1 tests for n variables
106Robust boundary value testing
Adds min- and max+ to test values just outside the range; expected outcome may be unclear and the program may crash on bad types
107Worst-case boundary testing
Cartesian product of the 5-value sets (all variables extreme at once): 5^n tests; basic boundary value testing is a subset
108Robust worst-case boundary testing
Cartesian product of the 7-value sets (including min- and max+): 7^n tests
109Where boundaries come from
Equivalence partitions, the specification, and common sense (e.g., 0); also internal boundaries such as Integer.MAX_VALUE or file sizes
110Benefits of boundary value analysis
Cheap, targets where bugs cluster, and works well for several independent variables representing bounded physical quantities
111Limitations of boundary value analysis
Boundaries may not exist (phone numbers, booleans) or be explicit (triangle sides); can leave gaps even for numeric programs; not effective stand-alone, only as a complement
112Combinatorial testing: the problem
Input described by parameters and values; can't run all combinations, so choose a 'good' subset (e.g., 4 parameters x 3 values = 81 combinations)
113Single-mode fault
A fault triggered by mishandling one particular part of the input
114Double-mode fault
A fault triggered by mishandling a particular combination of two inputs
115All singles
Each parameter value is exercised by at least one test
116Pairwise testing
Each pair of parameter values is exercised by at least one test
117Default-values approach
Pick a default value per parameter and vary one at a time; covers every single value (9 tests for the 4x3 example) but ignores parameter interactions
118Orthogonal array (OA)
A 2D array where, for any two columns, all pairwise combinations of values appear, evenly distributed (each the same number of times)
119Orthogonal array notation L_r(v^P)
r = number of rows, v = number of values, P = number of parameters; e.g., L4(2^3), L9(3^4)
120Coverage of L9(3^4)
100% (9/9) of pairwise combinations, 33% (9/27) of three-way, 11% (9/81) of four-way, using 9 tests instead of 81
121Benefits of orthogonal arrays (beyond fewer tests)
Systematic; guaranteed balanced pairwise coverage; catches interaction faults that default-values misses; beats random selection; constraints can be added; suspicious cases can be added manually
122Limitations of orthogonal arrays
Don't exist for every number of parameters and values; if none exists, use the smallest known OA that fits (e.g., L9(3^4) for three 3-value parameters)
123How to get an orthogonal array
Neil Sloane's online library, or tools such as OATS (AT&T) or AETG (Telcordia)
124Static analysis
Analyzing a program by examining its source code without executing it, looking for violations of good practice and specific errors
125Static analysis vs. testing
Complements testing but can't replace it (e.g., it won't notice a sort that sorts descending instead of ascending)
126Symbolic execution
Executing the program with symbolic input values (x0, y0) instead of concrete data, tracking a symbolic state and symbolic path condition
127Symbolic state
A mapping from program variables to symbolic expressions
128Symbolic path condition
A first-order formula over the symbolic inputs that must hold for a path to execute; sent to a constraint solver
129Why static analysis can't be perfect
The halting problem: no algorithm works for all programs, so tools answer 'yes', 'no', or 'not sure'
130How static analysis handles loops and recursion
Explores loops a small fixed number of iterations, caps the number of paths, and skips asynchronous paths, recursion, and function-pointer calls (it makes assumptions)
131Abstract domain (static analysis)
Each abstract state stands for many concrete states; the chosen domain limits what flaws can be found (e.g., relations between only two variables, integers only)
132Static analysis with missing source code
Tools must assume library behavior, so popular tools ship stubs/models for common libraries
133Static analysis tool trade-off
Powerful tools run slower and are harder to learn but find less obvious bugs; weaker tools are faster but need more hints from the user
134FindBugs-style bugs
Infinite recursion, ignored return values, forgetting to throw an exception, null-pointer dereferences, comparing unrelated types
135lint
Early static analysis tool for C; syntax pattern matching that misses errors visible by following data and control flow
136Best practice when adopting static analysis
Use the tool from day 1 and resolve warnings before they accumulate
137Statement coverage
Every non-conditional statement is executed by at least one test; the weakest criterion
138Weakness of statement coverage
Can reach 100% without ever seeing a condition be false; coverage percentage depends on how many statements are in each branch
139Branch (decision / edge) coverage
Every decision takes each possible outcome (true and false) at least once; stronger than statement coverage
140Weakness of branch coverage
Can be met without exposing a fault, and in compound decisions some conditions may never be evaluated (e.g., f() in A & (B | f()))
141Condition coverage
Every condition (a boolean expression with no boolean operators) in each decision takes both true and false at least once
142Weakness of condition coverage
For A ∨ B, tests (T,F) and (F,T) satisfy it but the decision is true both times, so it doesn't guarantee decision coverage
143Condition/decision coverage
Every condition AND every decision takes both outcomes
144Weakness of condition/decision coverage
For A ∨ B, tests (T,T) and (F,F) satisfy it but can't distinguish A ∨ B from A, B, or A ∧ B
145Multiple condition coverage
Every combination of condition outcomes within each decision is exercised: 2^n tests for n conditions
146Weakness of multiple condition coverage
Exponential cost: 30 conditions is about 1.07 billion tests
147MC/DC (modified condition/decision coverage)
Every decision and condition takes all outcomes, and each condition is shown to independently affect the decision by varying only that condition; needs about n+1 tests
148MC/DC tests for A ∨ B
{(T,F), (F,T), (F,F)}
149MC/DC tests for A ∧ B
{(T,T), (T,F), (F,T)}
150How to find MC/DC tests
Write the truth table; for each condition find two rows that differ only in that condition and give different decision outcomes; reuse rows to minimize tests
151Difficulties in MC/DC
Short-circuit operators (e.g., x != 0 && y/x > 15) and coupled conditions (e.g., (A ∧ B) ∨ (A ∧ C)) make some required tests infeasible
152Subsumption
Criterion C1 subsumes C2 if every test suite satisfying C1 also satisfies C2
153Control-flow subsumption hierarchy (strongest to weakest)
Multiple condition > MC/DC > Condition/decision > Decision (branch) > Statement
154Does condition coverage subsume decision coverage?
No; the A ∨ B example with (T,F) and (F,T) satisfies condition coverage but never makes the decision false
155How to find the strongest criterion a test suite satisfies
Draw the CFG, trace each test, mark covered statements, edges, and condition outcomes, then check criteria from strongest to weakest
156How code coverage tools work
Instrument the program (compiler flags, bytecode or source rewriting), count per basic block at run time, then map results back to source lines
157What coverage can't show
Code that should exist but doesn't
158Lesson from the COUNT program
A program can cover every path and still be wrong (feof() as loop condition ran one extra time); faults aren't just in your own logic, and the oracle matters
159Exhaustive path testing vs. exhaustive input testing
Covering all paths is not the same as testing all inputs, and loops make the number of paths huge