Testing During Implementation 1 *Testing During Implementation (Schach, Chap 15) Once Source Code...
-
Upload
caitlin-richardson -
Category
Documents
-
view
218 -
download
0
Transcript of Testing During Implementation 1 *Testing During Implementation (Schach, Chap 15) Once Source Code...
T
est
ing
Du
rin
g Im
ple
men
tati
on
1
*Testing During Implementation*Testing During Implementation (Schach, Chap 15)(Schach, Chap 15)
Once Source Code Available, can test code's ExecutionOnce Source Code Available, can test code's Execution Worst way — Random Testing: Plug in Arbitrary Input and
see what happens. Needed — a Systematic Way of Developing Test Cases
Why make a big deal about testing? Why not just release software and fix it after delivery?
F-16 autopilot inverted aircraft when F-16 autopilot inverted aircraft when crossing the equator (found in crossing the equator (found in simulator) simulator) (Neumann 86)(Neumann 86)
ESA lost Ariane 5 rocket due to ESA lost Ariane 5 rocket due to numerical precision in inertial reference system numerical precision in inertial reference system (Gleick 96)(Gleick 96) 64 bit floating point num for horizontal velocity converted to a
16 bit signed int. Conversion over 32,767 failed 37 seconds after liftoff ($500 Million).
T
est
ing
Du
rin
g Im
ple
men
tati
on
2
Two Approaches to Test Case SelectionTwo Approaches to Test Case Selection
Testing To Testing To SpecificationsSpecifications (a.k.a (a.k.a Black-Box Testing Black-Box Testing aka aka functional testing) functional testing) Focus: what module is supposed to do, not how it does it.
Testing To Testing To CodeCode (aka (aka Glass-Box Testing, Glass-Box Testing, logic-driven, or path-oriented testing).logic-driven, or path-oriented testing). Focus: how code in module is structured,
not what its supposed to do
Only info used in design of test cases is the spec doc
The code itself is tested, w/o regard to specifications
Events: External Conditions that set the Context of the module
T
est
ing
Du
rin
g Im
ple
men
tati
on
3
Role of Black/Glass Box focus in Test Case DevRole of Black/Glass Box focus in Test Case Dev
Regardless as to whether black or glass box based, need Regardless as to whether black or glass box based, need the identify the following for each test case:the identify the following for each test case:
Once actual test Once actual test case data set case data set determined, determined, what next?what next?
What is being tested. Ex: myATM.deposit(); How test data id’d Ex: User Scenario: deposit $10 The actual input data. ???????? The expected output. ???????? The actual output. ????????
• Need to inspect what the software actually produces as output and compare with what was expected.
T
est
ing
Du
rin
g Im
ple
men
tati
on
4
*Feasibility of Testing to Specifications*Feasibility of Testing to Specifications
Combinatorial Explosion Makes Completely Testing to Combinatorial Explosion Makes Completely Testing to Specifications ImpossibleSpecifications Impossible Example: Specifications For Data Processing Product
Include 5 Types of Commission And 7 Types of Discount. How Many Total Test Cases are needed?
Doesn’t matter if Commission and Discount computed in two entirely separate modules—the structure is irrelevant
T
est
ing
Du
rin
g Im
ple
men
tati
on
5
*ICE*ICE: : Feasibility of Completely Testing to SpecificationsFeasibility of Completely Testing to Specifications
Suppose Specification Includes 20 Factors, Each of Suppose Specification Includes 20 Factors, Each of Which can Take On any of 4 ValuesWhich can Take On any of 4 Values Determine how many test cases would be needed to
completely test to specification.
T
est
ing
Du
rin
g Im
ple
men
tati
on
6
*What about the Feasibility of Testing to Code?*What about the Feasibility of Testing to Code?
If it is desired that If it is desired that eacheach Path through Module be executed at Path through Module be executed at least once, Combinatorial Explosion May Resultleast once, Combinatorial Explosion May Result
// kmax in an int between 1..18// kmax in an int between 1..18
// myChar is A, or B, or C// myChar is A, or B, or C
T
est
ing
Du
rin
g Im
ple
men
tati
on
7
*What Does Exercising Every Path Promise?*What Does Exercising Every Path Promise?
Is it Possible to exercise Is it Possible to exercise EveryEvery Path w/o detecting Path w/o detecting EveryEvery Fault? Fault? if ((x + y + z) / 3 == x)
println ("x, y, z are equal in value");
else
println ("x, y, z are not equal");
T
est
ing
Du
rin
g Im
ple
men
tati
on
8
*More on the Feasibility of Testing to Code*More on the Feasibility of Testing to Code A Path can be tested only if it is presentA Path can be tested only if it is present
Weaker Criteria exist besides Path coverage:Weaker Criteria exist besides Path coverage: Branch Coverage: Exercise all branches of all
conditional statements Statement Coverage: Execute every statement
How many paths through this code?
T
est
ing
Du
rin
g Im
ple
men
tati
on
9
*Equivalence Testing and Boundary Value Analysis*Equivalence Testing and Boundary Value Analysis
Equivalence testing, combined with boundary value Equivalence testing, combined with boundary value analysis, is a black-box technique of selecting test casesanalysis, is a black-box technique of selecting test cases Goal: New test cases chosen to detect previously
undetected faults. An equivalence class is a set of test cases such that any one
member of the class is representative of any other member of the class.
• Assumes that any one member of the equivalence class is as good a test case as any other member of the class.
• Is this a good assumption? How are test cases selected?
T
est
ing
Du
rin
g Im
ple
men
tati
on
10
*Equivalence Classes Example*Equivalence Classes Example
Suppose Specifications For DBMS State that product must Suppose Specifications For DBMS State that product must handle any number of Records between 1 and 16,383. handle any number of Records between 1 and 16,383. Example: if System can handle 34 Records and 14,870
Records, then probably will work fine for 8,252 Records Basic ideaBasic idea: If system works for a test case in range : If system works for a test case in range
(1..16,383), then will probably work for any other test (1..16,383), then will probably work for any other test case in range; don’t bother with nearly redundant testing.case in range; don’t bother with nearly redundant testing.
T
est
ing
Du
rin
g Im
ple
men
tati
on
11
*Boundary-Value Analysis Probability of detecting a fault increases when test case on/next Probability of detecting a fault increases when test case on/next
to boundary of an equivalence class is selected.to boundary of an equivalence class is selected. Thus, when testing the database product, the following cases
could be selected for the Range 1..16,383
Combining Equivalence Classes With Boundary Value Analysis Yields Combining Equivalence Classes With Boundary Value Analysis Yields a (relatively) small set of Test Data with the a (relatively) small set of Test Data with the potentialpotential of uncovering a of uncovering a large # of Faults.large # of Faults.
Test CaseTest Case # records# records Equivalence class? Boundary value? Equivalence class? Boundary value?
11 0 records 0 records
22 1 record 1 record
33 2 records 2 records
44 723 records 723 records
55 16,382 records 16,382 records
66 16,383 records 16,383 records
77 16,384 records 16,384 records
Equivalence class 1 (& adjacent to boundary value)Equivalence class 1 (& adjacent to boundary value)
Eq Class 2; Adjacent to boundary valueEq Class 2; Adjacent to boundary value
Eq Class 2; Boundary valueEq Class 2; Boundary value
T
est
ing
Du
rin
g Im
ple
men
tati
on
12
*Boundary Value Analysis of Output Specs*Boundary Value Analysis of Output Specs
ICE:ICE: In 2001, Minimum Social Security (OASDI) Deduction From In 2001, Minimum Social Security (OASDI) Deduction From any one Paycheck was $0.00, and the Maximum was $4,984.80any one Paycheck was $0.00, and the Maximum was $4,984.80 Using Boundary Value Analysis, what Input Data should be
used to Test the Software that Implements the above deduction?
T
est
ing
Du
rin
g Im
ple
men
tati
on
13
*Functional*Functional TestingTesting
An alternative (lower-level) form of black-box testing is to base An alternative (lower-level) form of black-box testing is to base the test data on the the test data on the functionalityfunctionality of the module. of the module. In functional testing, each function in module is identified;
test data are devised to test each function separately. Functional testing can be difficult: Functional testing can be difficult:
The functions within a module may consist of lower-level functions, each of which must be tested first.
Lower-level functions may be not be independent. What problems arise when applying functional testing to OO?
T
est
ing
Du
rin
g Im
ple
men
tati
on
14
Shifting to Glass-Box TestingShifting to Glass-Box Testing
After black box testing: After black box testing: The requirements are shown to be fulfilled
for test cases considered. The interfaces are available and working.
So ... Why bother with glass-box testing? After all, the source code was tested by the black-box test cases.
T
est
ing
Du
rin
g Im
ple
men
tati
on
15
Glass-Box TestingGlass-Box Testing
Can be oriented towards Can be oriented towards Statement Coverage (Execute every
Statement at least once) Branch Coverage (Execute every Branch at least once) Path Coverage (Execute every Path at least once)
The code at hand is used to determine a test suite. The code at hand is used to determine a test suite. Ideally, you want Test Data that Exercises all Possible
Paths through your Code: • However, as previously discussed, likely is not possible
• Can Approximate by ensuring that each Path is Visited at least once, and considering equivalence classes.
T
est
ing
Du
rin
g Im
ple
men
tati
on
16
*Infeasible Code*Infeasible Code
It may not be possible to test It may not be possible to test a specific statementa specific statement May have an infeasible
path (“dead code”) in the module
Frequently this is evidence Frequently this is evidence of a faultof a fault
Many compilers can detect Many compilers can detect unreachable code as part of unreachable code as part of the parsing processthe parsing process
T
est
ing
Du
rin
g Im
ple
men
tati
on
17
Complexity Metrics: Making Testing ManageableComplexity Metrics: Making Testing Manageable
Goal Goal of Using a Software Complexity Metric: of Using a Software Complexity Metric: Highlight Modules Mostly Likely To Have Faults
Quality Assurance approach to Glass-Box Testing Quality Assurance approach to Glass-Box Testing Would be beneficial to be able to say, “Module M1 is
More “Complex” than Module M2” Problem: what do you do when you discover an Problem: what do you do when you discover an
unreasonably high Complexity Value for a Module?unreasonably high Complexity Value for a Module?
T
est
ing
Du
rin
g Im
ple
men
tati
on
18
Lines of Code as a Complexity MetricLines of Code as a Complexity Metric
Simplest Complexity Measure; Underlying Assumption: Simplest Complexity Measure; Underlying Assumption: There exists a Constant Probability p that Line of Code
Contains Fault. Based on the idea that the past can be used to predict the future.
Example:• Tester Believes Line of Code Has 2% Chance of
Containing Fault.• Module Under Test is 100 Lines Long, Probably Contains
2 Faults
T
est
ing
Du
rin
g Im
ple
men
tati
on
19
McCabe's Cyclomatic Complexity MetricMcCabe's Cyclomatic Complexity Metric
Cyclomatic Complexity Metric Cyclomatic Complexity Metric MM (McCabe, 76) (McCabe, 76) Essentially the Number of Decisions (branches) in Module
• M = #edges - #nodes +2 Can be used as a Metric for predicting the #
of Test Cases needed for Branch Coverage
M Value for Aegis System (Walsh,79)M Value for Aegis System (Walsh,79) 276 modules in Aegis 23% of modules with M > 10 contained 53% of detected faults Modules with M > 10 had 21% more faults per line of code
T
est
ing
Du
rin
g Im
ple
men
tati
on
20
ICE: Applying McCabe’s Metric ICE: Applying McCabe’s Metric
1.1. Use statement to graph conversionsUse statement to graph conversions2.2. Count num edges (#e), num nodes (#n)Count num edges (#e), num nodes (#n)3.3. Compute McCabe’s Metric M = #e-#n+2Compute McCabe’s Metric M = #e-#n+24.4. M > 10 is overly complex. Consider Re-M > 10 is overly complex. Consider Re-
designing Moduledesigning Module5.5. M value gives the recommended number of M value gives the recommended number of
test cases needed for branch coverage.test cases needed for branch coverage.
switch a {switch a { case 1: x =3;case 1: x =3;
break;break;case 2: if (b == 0) case 2: if (b == 0)
x=2;x=2; elseelse x=4;x=4; break;break;
case 3: while (c>0)case 3: while (c>0)
process(c);process(c); break;break;
}}
T
est
ing
Du
rin
g Im
ple
men
tati
on
21
Is Complete Black-Box/Glass-Box Testing Feasible?Is Complete Black-Box/Glass-Box Testing Feasible?
The The ArtArt of Testing (after reducing complexity of Testing (after reducing complexity via analysis of McCabe’s metric and others):via analysis of McCabe’s metric and others): Want: A Small, Manageable Set Of Test Cases:
• Maximize Chances of Detecting Fault, While
• Minimizing Chances of Wasting Test Case
What relative (Black/Glass Box) ordering of Test Cases What relative (Black/Glass Box) ordering of Test Cases will highlight as Many Faults As Possible?will highlight as Many Faults As Possible?
T
est
ing
Du
rin
g Im
ple
men
tati
on
22
Example: Testing a Tax Computation SystemExample: Testing a Tax Computation System
#include <iostream.h> #include <iostream.h> int main(void) { int main(void) { int numDependents, exemption; int numDependents, exemption; float income, taxSubTotal, taxTotal; float income, taxSubTotal, taxTotal; coutcout<<"Enter yearly income: "; "Enter yearly income: "; cin cin >> income; income;
// first if - check income ifif (income (income < 0) { 0) {
cout cout << “Cannot have ” “Cannot have ” << “negative income."; “negative income.";
return 0; return 0; } } coutcout<< “Give # dependents+self"; “Give # dependents+self"; cin cin >> numDependents; numDependents;
// second if - check dependents ifif (numDependents (numDependents <= 0) { 0) { coutcout<<“Need at least one “Need at least one
dependant"; dependant"; return 0; return 0;
}}
// third if (else-if) - compute tax subtotal
ifif (income (income << 10000) 10000) taxSubTotal = .02 * income; taxSubTotal = .02 * income; //bracket 1//bracket 1
elseelse if if (income (income < < 50000) 50000) //bracket 2//bracket 2
taxSubTotal = 200taxSubTotal = 200+.03*(income-10000);.03*(income-10000);
else else //bracket 3//bracket 3
taxSubTotal =1400taxSubTotal =1400+.04*(income-50000); .04*(income-50000);
exemption exemption = numDependents * 50; numDependents * 50;
taxTotataxTotal = taxSubTotal - exemption; taxSubTotal - exemption;
// last if - check negative tax
ifif (taxTotal (taxTotal<0) 0) //In case of negative tax taxTotal taxTotal=0; 0;
cout cout << income income <<‘ ‘ ‘ ‘ <<taxSubTotal; taxSubTotal;
cout cout << numDependents numDependents << ‘ ‘; ‘ ‘;
cout cout << exemption exemption << ‘ ‘ ‘ ‘ <<taxTotal; taxTotal;
} }
T
est
ing
Du
rin
g Im
ple
men
tati
on
23
Test Case Development for Path CoverageTest Case Development for Path Coverage
1st if 2nd if If-else-if Last if Result
1 inc < 0 doesn't matter doesn't matter doesn't matternegative income error
2 inc >= 0 numDep <= 0 doesn't matter doesn't matterinvalid dependents error
3 inc >= 0 numDep > 0 income < 10000 taxTotal < 0.02 bracket 0 tax due tax
4 inc>= 0 numDep > 010000 <= income < 50000
taxTotal < 0.03 bracket 0 tax due tax
There are four if statements in the code (and no loops), resulting in how many paths through the code? First Few Test Cases:
Group Exercise: Determine the Remaining 4 Test Cases
T
est
ing
Du
rin
g Im
ple
men
tati
on
24
Test Data SetsTest Data Sets
IncomeNum
DependentsExpected Result
1 -5 Don’t care negative income error
2 0 0 invalid dependents error
3 100 1 0 (bracket .02, negative tax)
4 20000 11 0 (bracket .03, negative tax)
To test the above, we need eight sets of data (values for income To test the above, we need eight sets of data (values for income and number of dependents), one to test each possible path. and number of dependents), one to test each possible path. Ranges for income are fairly evident for each case; we need only
select an appropriate number of dependents for each case. Below shows 4 test data sets corresponding to the first four test
cases described above, and the expected results (TaxTotal):
T
est
ing
Du
rin
g Im
ple
men
tati
on
25
*ICE: The remaining Equivalence Classes*ICE: The remaining Equivalence Classes
ifif (income (income < 0) { 0) { cout cout << “Cannot have ” “Cannot have ”
<< “negative income."; “negative income."; return 0; return 0;
} } coutcout<< “Give # dependents+self"; “Give # dependents+self"; cin cin >> numDependents; numDependents;
// third if (else-if) - compute tax subtotal
ifif (income (income << 10000) 10000) taxSubTotal = .02 * income; taxSubTotal = .02 * income;
elseelse if if (income (income < < 50000) 50000) taxSubTotal = 200 taxSubTotal = 200+.03*(income-10000); .03*(income-10000); else else taxSubTotal =1400 taxSubTotal =1400+.04*(income-50000); .04*(income-50000);
exemption exemption = numDependents * 50; numDependents * 50;
taxTotataxTotal = taxSubTotal - exemption; taxSubTotal - exemption;
// last if - check negative tax
ifif (taxTotal (taxTotal<0) 0) //In case of negative tax taxTotal taxTotal=0; 0;
cout cout << income income <<‘ ‘ ‘ ‘ <<taxSubTotal; taxSubTotal;
cout cout << numDependents numDependents << ‘ ‘; ‘ ‘;
cout cout << exemption exemption << ‘ ‘ ‘ ‘ <<taxTotal; taxTotal;
} }
#include <iostream.h> #include <iostream.h> int main(void) { int main(void) { int numDependents, exemption; int numDependents, exemption; float income, taxSubTotal, taxTotal; float income, taxSubTotal, taxTotal; coutcout<<"Enter yearly income: "; "Enter yearly income: "; cin cin >> income; income;
// first if - check income
// second if - check dependents ifif (numDependents (numDependents <= 0) { 0) { coutcout<<“Need at least one “Need at least one
dependant"; dependant"; return 0; return 0;
}}
T
est
ing
Du
rin
g Im
ple
men
tati
on
26
*ICE: Compute M value for Tax Software System*ICE: Compute M value for Tax Software System
#include <iostream.h> #include <iostream.h> int main(void) { int main(void) { int numDependents, exemption; int numDependents, exemption; float income, taxSubTotal, taxTotal; float income, taxSubTotal, taxTotal; coutcout<<"Enter yearly income: "; "Enter yearly income: "; cin cin >> income; income;
// first if - check income ifif (income (income < 0) { 0) {
cout cout << “Cannot have ” “Cannot have ” << “negative income."; “negative income.";
return 0; return 0; } } coutcout<< “Give # dependents+self"; “Give # dependents+self"; cin cin >> numDependents; numDependents;
// second if - check dependents ifif (numDependents (numDependents <= 0) { 0) { coutcout<<“Need at least one “Need at least one
dependant"; dependant"; return 0; return 0;
}}
// third if (else-if) - compute tax subtotal
ifif (income (income << 10000) 10000) taxSubTotal = .02 * income; taxSubTotal = .02 * income;
elseelse if if (income (income < < 50000) 50000) taxSubTotal = 200 taxSubTotal = 200+.03*(income-10000); .03*(income-10000); else else taxSubTotal =1400 taxSubTotal =1400+.04*(income-50000); .04*(income-50000);
exemption exemption = numDependents * 50; numDependents * 50;
taxTotataxTotal = taxSubTotal - exemption; taxSubTotal - exemption;
// last if - check negative tax
ifif (taxTotal (taxTotal<0) 0) //In case of negative tax taxTotal taxTotal=0; 0;
cout cout << income income <<‘ ‘ ‘ ‘ <<taxSubTotal; taxSubTotal;
cout cout << numDependents numDependents << ‘ ‘; ‘ ‘;
cout cout << exemption exemption << ‘ ‘ ‘ ‘ <<taxTotal; taxTotal;
} }
T
est
ing
Du
rin
g Im
ple
men
tati
on
27
*Fault Distribution In Modules Is Not Uniform*Fault Distribution In Modules Is Not Uniform
[Myers]: 47% of faults in OS/370 were in only 4% of the [Myers]: 47% of faults in OS/370 were in only 4% of the modulesmodules
[Endres]: DOS/VS (Release 28):[Endres]: DOS/VS (Release 28): 512 faults in a total of 202 modules
• 112 of the modules had only one fault• There were modules with 14, 15, 19 and 28 faults,
respectively – The latter three were the largest modules in the
product, with over 3000 lines of DOS macro assembler language
– The module with 14 faults was relatively small, and very unstable. What should be done with this module?
T
est
ing
Du
rin
g Im
ple
men
tati
on
28
* What does the detection of a fault tell us?* What does the detection of a fault tell us?
What does the detection of a fault within a module tell us What does the detection of a fault within a module tell us about the probability of the existence of additional faults in about the probability of the existence of additional faults in the same module?the same module?
[Myers]: When a module [Myers]: When a module has too many faults =>has too many faults => It is cheaper to redesign,
recode module than to try to fix its faults
Does finding a fault have any bearing on whether other faults are present?
T
est
ing
Du
rin
g Im
ple
men
tati
on
29
Comparison: Black-Box, Glass-Box, Code ReviewComparison: Black-Box, Glass-Box, Code Review
(Hwang, 1981): All three methods equally effective(Hwang, 1981): All three methods equally effective (Basili and Selby, 1987)(Basili and Selby, 1987) 32 professional programmers, 32 professional programmers,
42 advanced students 42 advanced students Professional programmers
• code reading detected more faults
• code reading had faster fault detection rate Advanced students
• code reading and black-box testing equally good
• both outperformed glass-box testing What Conclusions can be drawn from the above?What Conclusions can be drawn from the above?
T
est
ing
Du
rin
g Im
ple
men
tati
on
30
Information to Maintain on Formal Test Cases:Information to Maintain on Formal Test Cases:
What program unit was testedWhat program unit was tested How test set data was arrived at: equivalence classes, How test set data was arrived at: equivalence classes,
boundary values; boundary values; Type of coverage : branch coverage, etc. Type of coverage : branch coverage, etc.
Actual inputs (Include global variables, files, other state information when relevant)
Expected outputs Actual outputs
Value in running test set is in comparingValue in running test set is in comparing expected expected outputs outputs withwith actual outputs! actual outputs!
T
est
ing
Du
rin
g Im
ple
men
tati
on
31
*ICE: Test Case Development*ICE: Test Case Development
switch a {switch a {
case 1: x =3;case 1: x =3;
break;break;
case 2: if (b == 0) case 2: if (b == 0)
x=2;x=2;
elseelse
x=4;x=4;
break;break;
case 3: while (c>0)case 3: while (c>0)
process(c);process(c);
break;break;
}}
Give branch coverage test cases Give branch coverage test cases for the switch code (note: recall for the switch code (note: recall the previously computed M the previously computed M value) value)
Provide the following for each Provide the following for each test case:test case:
What is being testedWhat is being tested How test data was arrived atHow test data was arrived at Give the Give the
Actual input data set The expected output The actual output (simulate by
executing by hand here)