KEMBAR78
Software Testing - Introduction - Program based grammars | PPT
Introduction to Software Testing
Chapter 5.2
Program-based Grammars
Paul Ammann & Jeff Offutt
http://www.cs.gmu.edu/~offutt/softwaretest/
Introduction to Software Testing (Ch 5) © Ammann & Offutt 2
Applying Syntax-based Testing to Programs
• Syntax-based criteria originated with programs and
have been used most with programs
• BNF criteria are most commonly used to test compilers
• Mutation testing criteria are most commonly used for
unit testing and integration testing of classes
Introduction to Software Testing (Ch 5) © Ammann & Offutt 3
Instantiating Grammar-Based Testing
Grammar-Based Testing
Program-based Integration Model-Based Input-Based
• Compiler testing
• Valid and invalid strings
Grammar
String
mutation
• Program mutation
• Valid strings
• Mutants are not tests
• Must kill mutants
• Input validation testing
• XML and others
• Valid strings
Grammar
• Test how classes interact
• Valid strings
• Mutants are not tests
• Must kill mutants
• Includes OO
String
mutation
• FSMs
• Model checking
• Valid strings
• Traces are tests
String
mutation
• Input validation
testing
• XML and others
• Invalid strings
• No ground strings
• Mutants are tests
String
mutation
5.2
Introduction to Software Testing (Ch 5) © Ammann & Offutt 4
BNF Testing for Compilers (5.2.1)
• Testing compilers is very complicated
– Millions of correct programs !
– Compilers must recognize and reject incorrect programs
• BNF criteria can be used to generate programs to test all
language features that compilers must process
• This is a very specialized application and not discussed in detail
Program-based Grammars (5.2.2)
• The original and most widely known application of
syntax-based testing is to modify programs
• Operators modify a ground string (program under
test) to create mutant programs
• Mutant programs must compile correctly (valid
strings)
• Mutants are not tests, but used to find tests
• Once mutants are defined, tests must be found to cause
mutants to fail when executed
• This is called “killing mutants”
Introduction to Software Testing (Ch 5) © Ammann & Offutt 5
Killing Mutants
• If mutation operators are designed well, the resulting tests will
be very powerful
• Different operators must be defined for different programming
languages and goals
• Testers can keep adding tests until all mutants have been killed
– Dead mutant : A test case has killed it
– Stillborn mutant : Syntactically illegal
– Trivial mutant : Almost every test can kill it
– Equivalent mutant : No test can kill it (equivalent to original program)
Introduction to Software Testing (Ch 5) © Ammann & Offutt 6
Given a mutant m  M for a ground string program P
and a test t, t is said to kill m if and only if the output
of t on P is different from the output of t on m.
Introduction to Software Testing (Ch 5) © Ammann & Offutt 7
Program-based Grammars
Original Method
int Min (int A, int B)
{
int minVal;
minVal = A;
if (B < A)
{
minVal = B;
}
return (minVal);
} // end Min
With Embedded Mutants
int Min (int A, int B)
{
int minVal;
minVal = A;
∆ 1 minVal = B;
if (B < A)
∆ 2 if (B > A)
∆ 3 if (B < minVal)
{
minVal = B;
∆ 4 Bomb ();
∆ 5 minVal = A;
∆ 6 minVal = failOnZero (B);
}
return (minVal);
} // end Min
6 mutants
Each represents a
separate program
Replace one variable
Replace one variable
with another
with another
Changes operator
Changes operator
Immediate runtime
Immediate runtime
failure … if reached
failure … if reached
Immediate runtime
Immediate runtime
failure if B==0 else
failure if B==0 else
does nothing
does nothing
Introduction to Software Testing (Ch 5) © Ammann & Offutt 8
Syntax-Based Coverage Criteria
Mutation Coverage (MC)
Mutation Coverage (MC) : For each
: For each m
m  M
M, TR contains
, TR contains
exactly one requirement, to kill
exactly one requirement, to kill m
m.
.
• The RIP model from chapter 1:
• Reachability : The test causes the faulty statement to be
reached (in mutation – the mutated statement)
• Infection : The test causes the faulty statement to result in an
incorrect state
• Propagation : The incorrect state propagates to incorrect
output
• The RIP model leads to two variants of mutation coverage …
Introduction to Software Testing (Ch 5) © Ammann & Offutt 9
Syntax-Based Coverage Criteria
1) Strongly Killing Mutants:
Given a mutant m  M for a program P and a test t, t is said to
strongly kill m if and only if the output of t on P is different
from the output of t on m
2) Weakly Killing Mutants:
Given a mutant m  M that modifies a location l in a program
P, and a test t, t is said to weakly kill m if and only if the state
of the execution of P on t is different from the state of the
execution of m immediately on t after l
• Weakly killing satisfies reachability and infection, but not
propagation
Introduction to Software Testing (Ch 5) © Ammann & Offutt 10
Weak Mutation
Weak Mutation Coverage (WMC)
Weak Mutation Coverage (WMC) : For each
: For each m
m  M
M, TR
, TR
contains exactly one requirement, to weakly kill
contains exactly one requirement, to weakly kill m
m.
.
• “Weak mutation” is so named because it is easier to kill
mutants under this assumption
• Weak mutation also requires less analysis
• A few mutants can be killed under weak mutation but not
under strong mutation (no propagation)
• In practice, there is little difference
Introduction to Software Testing (Ch 5) © Ammann & Offutt 11
Weak Mutation Example
• The complete test specification to kill mutant 1:
• Reachability : true // Always get to that statement
• Infection : A ≠ B
• Propagation: (B < A) = false // Skip the next assignment
• Full Test Specification : true  (A ≠ B)  ((B < A) = false)
≡ (A ≠ B)  (B ≥A)
≡ (B > A)
• (A = 5, B = 3) will weakly kill mutant 1, but not strongly
minVal = A;
∆ 1 minVal = B;
if (B < A)
minVal = B;
• Mutant 1 in the Min( ) example is:
Introduction to Software Testing (Ch 5) © Ammann & Offutt 12
Equivalent Mutation Example
• Mutant 3 in the Min() example is equivalent:
minVal = A;
if (B < A)
∆ 3 if (B < minVal)
• The infection condition is “(B < A) != (B < minVal)”
• However, the previous statement was “minVal = A”
– Substituting, we get: “(B < A) != (B < A)”
– This is a logical contradiction !
• Thus no input can kill this mutant
Introduction to Software Testing (Ch 5) © Ammann & Offutt 13
1 boolean isEven (int X)
2 {
3 if (X < 0)
4 X = 0 - X;
∆ 4 X = 0;
5 if (double) (X/2) == ((double) X) / 2.0
6 return (true);
7 else
8 return (false);
9 }
Strong Versus Weak Mutation
Reachability
Reachability : X < 0
: X < 0
Infection
Infection : X != 0
: X != 0
(X = -6) will kill mutant
(X = -6) will kill mutant
4 under
4 under weak mutation
weak mutation
Propagation
Propagation :
:
((double) ((0-X)/2) == ((double) 0-X) / 2.0)
((double) ((0-X)/2) == ((double) 0-X) / 2.0)
!= ((double) (0/2) == ((double) 0) / 2.0)
!= ((double) (0/2) == ((double) 0) / 2.0)
That is, X is
That is, X is not
not even …
even …
Thus (X = -6) does
Thus (X = -6) does not
not kill the mutant under
kill the mutant under
strong mutation
strong mutation
Introduction to Software Testing (Ch 5) © Ammann & Offutt 14
Automated
Automated
steps
steps
Testing Programs with Mutation
Input test
method
Prog Create
mutants
Run T
on P
Run mutants:
• schema-based
• weak
• selective
Eliminate
ineffective
TCs
Generate
test cases
Run
equivalence
detector
Threshold
reached
?
Define
threshold
no
P (T)
correct
?
yes
Fix
P
no
Introduction to Software Testing (Ch 5) © Ammann & Offutt 15
Why Mutation Works
• This is not an absolute !
• The mutants guide the tester to an effective set of tests
• A very challenging problem :
– Find a fault and a set of mutation-adequate tests that do not find the fault
• Of course, this depends on the mutation operators …
Fundamental Premise of Mutation Testing
Fundamental Premise of Mutation Testing
If the software contains a fault, there will
If the software contains a fault, there will
usually be a set of mutants that can only be
usually be a set of mutants that can only be
killed by a test case that also detects that fault
killed by a test case that also detects that fault
Introduction to Software Testing (Ch 5) © Ammann & Offutt 16
Designing Mutation Operators
• At the method level, mutation operators for different
programming languages are similar
• Mutation operators do one of two things :
– Mimic typical programmer mistakes ( incorrect variable name )
– Encourage common test heuristics ( cause expressions to be 0 )
• Researchers design lots of operators, then experimentally select
the most useful
Effective Mutation Operators
Effective Mutation Operators
If tests that are created specifically to kill mutants created
If tests that are created specifically to kill mutants created
by a collection of mutation operators
by a collection of mutation operators O
O = {
= {o1, o2,
o1, o2, …} also
…} also
kill mutants created by all remaining mutation operators
kill mutants created by all remaining mutation operators
with very high probability, then
with very high probability, then O
O defines an
defines an effective
effective set of
set of
mutation operators
mutation operators
Introduction to Software Testing (Ch 5) © Ammann & Offutt 17
Mutation Operators for Java
Each occurrence of one of the arithmetic operators +, - ,*, / , and % is
replaced by each of the other operators. In addition, each is replaced by the
special mutation operators leftOp, and rightOp.
2. AOR –– Arithmetic Operator Replacement:
Each arithmetic expression (and subexpression) is modified by the functions
abs(), negAbs(), and failOnZero().
1. ABS –– Absolute Value Insertion:
Examples:
a = m * (o + p);
a = m * (o + p);
∆
∆1 a = abs (m * (o + p));
1 a = abs (m * (o + p));
∆
∆2 a = m * abs ((o + p));
2 a = m * abs ((o + p));
∆
∆3 a = failOnZero (m * (o + p));
3 a = failOnZero (m * (o + p));
Examples:
a = m * (o + p);
a = m * (o + p);
∆
∆1 a = m + (o + p);
1 a = m + (o + p);
∆
∆2 a = m * (o * p);
2 a = m * (o * p);
∆
∆3 a = m
3 a = m leftOp
leftOp (o + p);
(o + p);
Introduction to Software Testing (Ch 5) © Ammann & Offutt 18
Mutation Operators for Java (2)
Each occurrence of one of the relational operators (<, ≤, >, ≥, =, ≠) is replaced
by each of the other operators and by falseOp and trueOp.
3. ROR –– Relational Operator Replacement:
Examples:
if (X <= Y)
if (X <= Y)
∆
∆1 if (X > Y)
1 if (X > Y)
∆
∆2 if (X < Y)
2 if (X < Y)
∆
∆3 if (X
3 if (X falseOp
falseOp Y) // always returns false
Y) // always returns false
Each occurrence of one of the logical operators (and - &&, or - || , and with no
conditional evaluation - &, or with no conditional evaluation - |, not equivalent
- ^) is replaced by each of the other operators; in addition, each is replaced by
falseOp, trueOp, leftOp, and rightOp.
4. COR –– Conditional Operator Replacement:
Examples:
if (X <= Y && a > 0)
if (X <= Y && a > 0)
∆
∆1 if (X <= Y || a > 0)
1 if (X <= Y || a > 0)
∆
∆2 if (X <= Y
2 if (X <= Y leftOp
leftOp a > 0) // returns result of left clause
a > 0) // returns result of left clause
Introduction to Software Testing (Ch 5) © Ammann & Offutt 19
Mutation Operators for Java (4)
5. SOR –– Shift Operator Replacement:
Each occurrence of one of the shift operators <<, >>, and >>> is replaced by
each of the other operators. In addition, each is replaced by the special
mutation operator leftOp.
Each occurrence of one of the logical operators (bitwise and - &, bitwise or
- |, exclusive or - ^) is replaced by each of the other operators; in addition,
each is replaced by leftOp and rightOp.
6. LOR –– Logical Operator Replacement:
Examples:
byte b = (byte) 16;
byte b = (byte) 16;
b = b >> 2;
b = b >> 2;
∆
∆1 b = b << 2;
1 b = b << 2;
∆
∆2 b = b
2 b = b leftOp
leftOp 2; // result is b
2; // result is b
Examples:
int a = 60; int b = 13;
int a = 60; int b = 13;
int c = a & b;
int c = a & b;
∆
∆1 int c = a | b;
1 int c = a | b;
∆
∆2 int c = a
2 int c = a rightOp
rightOp b; // result is b
b; // result is b
Introduction to Software Testing (Ch 5) © Ammann & Offutt 20
Mutation Operators for Java (5)
Each occurrence of one of the assignment operators (+=, -=, *=, /=, %=, &=, |
=, ^=, <<=, >>=, >>>=) is replaced by each of the other operators.
7. ASR –– Assignment Operator Replacement:
8. UOI –– Unary Operator Insertion:
Each unary operator (arithmetic +, arithmetic -, conditional !, logical ~) is
inserted in front of each expression of the correct type.
Examples:
a = m * (o + p);
a = m * (o + p);
∆
∆1 a += m * (o + p);
1 a += m * (o + p);
∆
∆2 a *= m * (o + p);
2 a *= m * (o + p);
Examples:
a = m * (o + p);
a = m * (o + p);
∆
∆1 a = m * -(o + p);
1 a = m * -(o + p);
∆
∆2 a = -(m * (o + p));
2 a = -(m * (o + p));
Introduction to Software Testing (Ch 5) © Ammann & Offutt 21
Mutation Operators for Java (6)
Each unary operator (arithmetic +, arithmetic -, conditional !, logical~) is
deleted.
9. UOD –– Unary Operator Deletion:
Examples:
if !(X <= Y && !Z)
if !(X <= Y && !Z)
∆
∆1 if (X > Y && !Z)
1 if (X > Y && !Z)
∆
∆2 if !(X < Y && Z)
2 if !(X < Y && Z)
Each variable reference is replaced by every other variable of the appropriate
type that is declared in the current scope.
10. SVR –– Scalar Variable Replacement:
Examples:
a = m * (o + p);
a = m * (o + p);
∆
∆ 1 a = o * (o + p);
1 a = o * (o + p);
∆
∆ 2 a = m * (m + p);
2 a = m * (m + p);
∆
∆ 3 a = m * (o + o);
3 a = m * (o + o);
∆
∆ 4 p = m * (o + p);
4 p = m * (o + p);
Introduction to Software Testing (Ch 5) © Ammann & Offutt 22
Mutation Operators for Java (7)
11. BSR –– Bomb Statement Replacement:
Each statement is replaced by a special Bomb() function.
Example:
a = m * (o + p);
a = m * (o + p);
∆
∆1
1 Bomb
Bomb() // Raises exception when reached
() // Raises exception when reached
Introduction to Software Testing (Ch 5) © Ammann & Offutt 23
Summary : Subsumption of Other Criteria
• Mutation is widely considered the strongest test criterion
– And most expensive !
– By far the most test requirements (each mutant)
– Not always the most tests
• Mutation subsumes other criteria by including specific mutation
operators
• Subsumption can only be defined for weak mutation – other
criteria impose local requirements, like weak mutation
– Node coverage
– Edge coverage
– Clause coverage
– General active clause coverage: Yes – Requirement on single tests
– Correlated active clause coverage: No – Requirement on pairs of tests
– All-defs data flow coverage

Software Testing - Introduction - Program based grammars

  • 1.
    Introduction to SoftwareTesting Chapter 5.2 Program-based Grammars Paul Ammann & Jeff Offutt http://www.cs.gmu.edu/~offutt/softwaretest/
  • 2.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 2 Applying Syntax-based Testing to Programs • Syntax-based criteria originated with programs and have been used most with programs • BNF criteria are most commonly used to test compilers • Mutation testing criteria are most commonly used for unit testing and integration testing of classes
  • 3.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 3 Instantiating Grammar-Based Testing Grammar-Based Testing Program-based Integration Model-Based Input-Based • Compiler testing • Valid and invalid strings Grammar String mutation • Program mutation • Valid strings • Mutants are not tests • Must kill mutants • Input validation testing • XML and others • Valid strings Grammar • Test how classes interact • Valid strings • Mutants are not tests • Must kill mutants • Includes OO String mutation • FSMs • Model checking • Valid strings • Traces are tests String mutation • Input validation testing • XML and others • Invalid strings • No ground strings • Mutants are tests String mutation 5.2
  • 4.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 4 BNF Testing for Compilers (5.2.1) • Testing compilers is very complicated – Millions of correct programs ! – Compilers must recognize and reject incorrect programs • BNF criteria can be used to generate programs to test all language features that compilers must process • This is a very specialized application and not discussed in detail
  • 5.
    Program-based Grammars (5.2.2) •The original and most widely known application of syntax-based testing is to modify programs • Operators modify a ground string (program under test) to create mutant programs • Mutant programs must compile correctly (valid strings) • Mutants are not tests, but used to find tests • Once mutants are defined, tests must be found to cause mutants to fail when executed • This is called “killing mutants” Introduction to Software Testing (Ch 5) © Ammann & Offutt 5
  • 6.
    Killing Mutants • Ifmutation operators are designed well, the resulting tests will be very powerful • Different operators must be defined for different programming languages and goals • Testers can keep adding tests until all mutants have been killed – Dead mutant : A test case has killed it – Stillborn mutant : Syntactically illegal – Trivial mutant : Almost every test can kill it – Equivalent mutant : No test can kill it (equivalent to original program) Introduction to Software Testing (Ch 5) © Ammann & Offutt 6 Given a mutant m  M for a ground string program P and a test t, t is said to kill m if and only if the output of t on P is different from the output of t on m.
  • 7.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 7 Program-based Grammars Original Method int Min (int A, int B) { int minVal; minVal = A; if (B < A) { minVal = B; } return (minVal); } // end Min With Embedded Mutants int Min (int A, int B) { int minVal; minVal = A; ∆ 1 minVal = B; if (B < A) ∆ 2 if (B > A) ∆ 3 if (B < minVal) { minVal = B; ∆ 4 Bomb (); ∆ 5 minVal = A; ∆ 6 minVal = failOnZero (B); } return (minVal); } // end Min 6 mutants Each represents a separate program Replace one variable Replace one variable with another with another Changes operator Changes operator Immediate runtime Immediate runtime failure … if reached failure … if reached Immediate runtime Immediate runtime failure if B==0 else failure if B==0 else does nothing does nothing
  • 8.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 8 Syntax-Based Coverage Criteria Mutation Coverage (MC) Mutation Coverage (MC) : For each : For each m m  M M, TR contains , TR contains exactly one requirement, to kill exactly one requirement, to kill m m. . • The RIP model from chapter 1: • Reachability : The test causes the faulty statement to be reached (in mutation – the mutated statement) • Infection : The test causes the faulty statement to result in an incorrect state • Propagation : The incorrect state propagates to incorrect output • The RIP model leads to two variants of mutation coverage …
  • 9.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 9 Syntax-Based Coverage Criteria 1) Strongly Killing Mutants: Given a mutant m  M for a program P and a test t, t is said to strongly kill m if and only if the output of t on P is different from the output of t on m 2) Weakly Killing Mutants: Given a mutant m  M that modifies a location l in a program P, and a test t, t is said to weakly kill m if and only if the state of the execution of P on t is different from the state of the execution of m immediately on t after l • Weakly killing satisfies reachability and infection, but not propagation
  • 10.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 10 Weak Mutation Weak Mutation Coverage (WMC) Weak Mutation Coverage (WMC) : For each : For each m m  M M, TR , TR contains exactly one requirement, to weakly kill contains exactly one requirement, to weakly kill m m. . • “Weak mutation” is so named because it is easier to kill mutants under this assumption • Weak mutation also requires less analysis • A few mutants can be killed under weak mutation but not under strong mutation (no propagation) • In practice, there is little difference
  • 11.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 11 Weak Mutation Example • The complete test specification to kill mutant 1: • Reachability : true // Always get to that statement • Infection : A ≠ B • Propagation: (B < A) = false // Skip the next assignment • Full Test Specification : true  (A ≠ B)  ((B < A) = false) ≡ (A ≠ B)  (B ≥A) ≡ (B > A) • (A = 5, B = 3) will weakly kill mutant 1, but not strongly minVal = A; ∆ 1 minVal = B; if (B < A) minVal = B; • Mutant 1 in the Min( ) example is:
  • 12.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 12 Equivalent Mutation Example • Mutant 3 in the Min() example is equivalent: minVal = A; if (B < A) ∆ 3 if (B < minVal) • The infection condition is “(B < A) != (B < minVal)” • However, the previous statement was “minVal = A” – Substituting, we get: “(B < A) != (B < A)” – This is a logical contradiction ! • Thus no input can kill this mutant
  • 13.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 13 1 boolean isEven (int X) 2 { 3 if (X < 0) 4 X = 0 - X; ∆ 4 X = 0; 5 if (double) (X/2) == ((double) X) / 2.0 6 return (true); 7 else 8 return (false); 9 } Strong Versus Weak Mutation Reachability Reachability : X < 0 : X < 0 Infection Infection : X != 0 : X != 0 (X = -6) will kill mutant (X = -6) will kill mutant 4 under 4 under weak mutation weak mutation Propagation Propagation : : ((double) ((0-X)/2) == ((double) 0-X) / 2.0) ((double) ((0-X)/2) == ((double) 0-X) / 2.0) != ((double) (0/2) == ((double) 0) / 2.0) != ((double) (0/2) == ((double) 0) / 2.0) That is, X is That is, X is not not even … even … Thus (X = -6) does Thus (X = -6) does not not kill the mutant under kill the mutant under strong mutation strong mutation
  • 14.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 14 Automated Automated steps steps Testing Programs with Mutation Input test method Prog Create mutants Run T on P Run mutants: • schema-based • weak • selective Eliminate ineffective TCs Generate test cases Run equivalence detector Threshold reached ? Define threshold no P (T) correct ? yes Fix P no
  • 15.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 15 Why Mutation Works • This is not an absolute ! • The mutants guide the tester to an effective set of tests • A very challenging problem : – Find a fault and a set of mutation-adequate tests that do not find the fault • Of course, this depends on the mutation operators … Fundamental Premise of Mutation Testing Fundamental Premise of Mutation Testing If the software contains a fault, there will If the software contains a fault, there will usually be a set of mutants that can only be usually be a set of mutants that can only be killed by a test case that also detects that fault killed by a test case that also detects that fault
  • 16.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 16 Designing Mutation Operators • At the method level, mutation operators for different programming languages are similar • Mutation operators do one of two things : – Mimic typical programmer mistakes ( incorrect variable name ) – Encourage common test heuristics ( cause expressions to be 0 ) • Researchers design lots of operators, then experimentally select the most useful Effective Mutation Operators Effective Mutation Operators If tests that are created specifically to kill mutants created If tests that are created specifically to kill mutants created by a collection of mutation operators by a collection of mutation operators O O = { = {o1, o2, o1, o2, …} also …} also kill mutants created by all remaining mutation operators kill mutants created by all remaining mutation operators with very high probability, then with very high probability, then O O defines an defines an effective effective set of set of mutation operators mutation operators
  • 17.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 17 Mutation Operators for Java Each occurrence of one of the arithmetic operators +, - ,*, / , and % is replaced by each of the other operators. In addition, each is replaced by the special mutation operators leftOp, and rightOp. 2. AOR –– Arithmetic Operator Replacement: Each arithmetic expression (and subexpression) is modified by the functions abs(), negAbs(), and failOnZero(). 1. ABS –– Absolute Value Insertion: Examples: a = m * (o + p); a = m * (o + p); ∆ ∆1 a = abs (m * (o + p)); 1 a = abs (m * (o + p)); ∆ ∆2 a = m * abs ((o + p)); 2 a = m * abs ((o + p)); ∆ ∆3 a = failOnZero (m * (o + p)); 3 a = failOnZero (m * (o + p)); Examples: a = m * (o + p); a = m * (o + p); ∆ ∆1 a = m + (o + p); 1 a = m + (o + p); ∆ ∆2 a = m * (o * p); 2 a = m * (o * p); ∆ ∆3 a = m 3 a = m leftOp leftOp (o + p); (o + p);
  • 18.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 18 Mutation Operators for Java (2) Each occurrence of one of the relational operators (<, ≤, >, ≥, =, ≠) is replaced by each of the other operators and by falseOp and trueOp. 3. ROR –– Relational Operator Replacement: Examples: if (X <= Y) if (X <= Y) ∆ ∆1 if (X > Y) 1 if (X > Y) ∆ ∆2 if (X < Y) 2 if (X < Y) ∆ ∆3 if (X 3 if (X falseOp falseOp Y) // always returns false Y) // always returns false Each occurrence of one of the logical operators (and - &&, or - || , and with no conditional evaluation - &, or with no conditional evaluation - |, not equivalent - ^) is replaced by each of the other operators; in addition, each is replaced by falseOp, trueOp, leftOp, and rightOp. 4. COR –– Conditional Operator Replacement: Examples: if (X <= Y && a > 0) if (X <= Y && a > 0) ∆ ∆1 if (X <= Y || a > 0) 1 if (X <= Y || a > 0) ∆ ∆2 if (X <= Y 2 if (X <= Y leftOp leftOp a > 0) // returns result of left clause a > 0) // returns result of left clause
  • 19.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 19 Mutation Operators for Java (4) 5. SOR –– Shift Operator Replacement: Each occurrence of one of the shift operators <<, >>, and >>> is replaced by each of the other operators. In addition, each is replaced by the special mutation operator leftOp. Each occurrence of one of the logical operators (bitwise and - &, bitwise or - |, exclusive or - ^) is replaced by each of the other operators; in addition, each is replaced by leftOp and rightOp. 6. LOR –– Logical Operator Replacement: Examples: byte b = (byte) 16; byte b = (byte) 16; b = b >> 2; b = b >> 2; ∆ ∆1 b = b << 2; 1 b = b << 2; ∆ ∆2 b = b 2 b = b leftOp leftOp 2; // result is b 2; // result is b Examples: int a = 60; int b = 13; int a = 60; int b = 13; int c = a & b; int c = a & b; ∆ ∆1 int c = a | b; 1 int c = a | b; ∆ ∆2 int c = a 2 int c = a rightOp rightOp b; // result is b b; // result is b
  • 20.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 20 Mutation Operators for Java (5) Each occurrence of one of the assignment operators (+=, -=, *=, /=, %=, &=, | =, ^=, <<=, >>=, >>>=) is replaced by each of the other operators. 7. ASR –– Assignment Operator Replacement: 8. UOI –– Unary Operator Insertion: Each unary operator (arithmetic +, arithmetic -, conditional !, logical ~) is inserted in front of each expression of the correct type. Examples: a = m * (o + p); a = m * (o + p); ∆ ∆1 a += m * (o + p); 1 a += m * (o + p); ∆ ∆2 a *= m * (o + p); 2 a *= m * (o + p); Examples: a = m * (o + p); a = m * (o + p); ∆ ∆1 a = m * -(o + p); 1 a = m * -(o + p); ∆ ∆2 a = -(m * (o + p)); 2 a = -(m * (o + p));
  • 21.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 21 Mutation Operators for Java (6) Each unary operator (arithmetic +, arithmetic -, conditional !, logical~) is deleted. 9. UOD –– Unary Operator Deletion: Examples: if !(X <= Y && !Z) if !(X <= Y && !Z) ∆ ∆1 if (X > Y && !Z) 1 if (X > Y && !Z) ∆ ∆2 if !(X < Y && Z) 2 if !(X < Y && Z) Each variable reference is replaced by every other variable of the appropriate type that is declared in the current scope. 10. SVR –– Scalar Variable Replacement: Examples: a = m * (o + p); a = m * (o + p); ∆ ∆ 1 a = o * (o + p); 1 a = o * (o + p); ∆ ∆ 2 a = m * (m + p); 2 a = m * (m + p); ∆ ∆ 3 a = m * (o + o); 3 a = m * (o + o); ∆ ∆ 4 p = m * (o + p); 4 p = m * (o + p);
  • 22.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 22 Mutation Operators for Java (7) 11. BSR –– Bomb Statement Replacement: Each statement is replaced by a special Bomb() function. Example: a = m * (o + p); a = m * (o + p); ∆ ∆1 1 Bomb Bomb() // Raises exception when reached () // Raises exception when reached
  • 23.
    Introduction to SoftwareTesting (Ch 5) © Ammann & Offutt 23 Summary : Subsumption of Other Criteria • Mutation is widely considered the strongest test criterion – And most expensive ! – By far the most test requirements (each mutant) – Not always the most tests • Mutation subsumes other criteria by including specific mutation operators • Subsumption can only be defined for weak mutation – other criteria impose local requirements, like weak mutation – Node coverage – Edge coverage – Clause coverage – General active clause coverage: Yes – Requirement on single tests – Correlated active clause coverage: No – Requirement on pairs of tests – All-defs data flow coverage