Mutation Testing Moonzoo Kim School of Computing KAIST

Slides:



Advertisements
Similar presentations
1 Software Testing and Quality Assurance Lecture 9 - Software Testing Techniques.
Advertisements

Introduction to Software Testing Chapter 5.2 Program-based Grammars Paul Ammann & Jeff Offutt
Software Testing and Validation SWE 434
Kyle Mundt February 3,  Richard Lipton, 1971  A way of testing your tests  Alter your code in various ways  Check to see if tests fail on altered.
© SERG Dependable Software Systems (Mutation) Dependable Software Systems Topics in Mutation Testing and Program Perturbation Material drawn from [Offutt.
Introduction to Software Testing
Introduction to Software Testing Chapter 8.1 Building Testing Tools –Instrumentation Paul Ammann & Jeff Offutt
SWE 637: Test Criteria and Definitions Tao Xie Prepared based on Slides by ©Paul Ammann and Jeff Offutt Revised by Tao Xie.
Software testing techniques Software testing techniques Mutation testing Presentation on the seminar Kaunas University of Technology.
Test Coverage CS-300 Fall 2005 Supreeth Venkataraman.
637 – Introduction (Ch 1) Introduction to Software Testing Chapter 1 Jeff Offutt Information & Software Engineering SWE 437 Software Testing
Syntax-Based Testing Mingzhe Du Hongying Du Dharani Chintapatla.
First delivery of the course Software Quality and Testing Katerina Zdravkova, Anastas Mišev
Introduction to Software Testing Paul Ammann & Jeff Offutt Updated 24-August 2010.
Introduction to Software Testing. OUTLINE Introduction to Software Testing (Ch 1) 2 1.Spectacular Software Failures 2.Why Test? 3.What Do We Do When We.
Software Testing Part II March, Fault-based Testing Methodology (white-box) 2 Mutation Testing.
Software Testing Syntax-based Testing. Syntax Coverage Four Structures for Modeling Software Graphs Logic Input Space Syntax Use cases Specs Design Source.
Introduction to Software Testing Chapter 9.2 Program-based Grammars Paul Ammann & Jeff Offutt
Week 5-6 MondayTuesdayWednesdayThursdayFriday Testing III No reading Group meetings Testing IVSection ZFR due ZFR demos Progress report due Readings out.
Workshop on Integrating Software Testing into Programming Courses (WISTPC14:2) Friday July 18, 2014 Introduction to Software Testing.
Mutation Testing Breaking the application to test it.
Foundations of Software Testing Chapter 7: Test Adequacy Measurement and Enhancement Using Mutation Last update: September 3, 2007 These slides are copyrighted.
MUTACINIS TESTAVIMAS Benediktas Knispelis, IFM-2/2 Mutation testing.
Foundations of Software Testing Chapter 7: Test Adequacy Measurement and Enhancement Using Mutation Last update: September 3, 2007 These slides are copyrighted.
Is Mutation Analysis Ready for Prime Time? Jeff Offutt George Mason University Based on the book Introduction.
Software Testing and Quality Assurance Syntax-Based Testing (2) 1.
Introduction to Software Testing (2nd edition) Chapter 5 Criteria-Based Test Design Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Data Flow Analysis Suman Jana
Paul Ammann & Jeff Offutt
Generating Automated Tests from Behavior Models
Introduction to Software Testing Chapter 9.2 Program-based Grammars
Software Testing and Maintenance 1
Paul Ammann & Jeff Offutt
Input Space Partition Testing CS 4501 / 6501 Software Testing
Mutation testing Julius Purvinis IFM-0/2.
Faults, Errors, Failures CS 4501 / 6501 Software Testing
Paul Ammann & Jeff Offutt
Structural testing, Path Testing
Types of Testing Visit to more Learning Resources.
Syntax-based Testing CS 4501 / 6501 Software Testing
Introduction to Software Testing Chapter 5.1 Syntax-based Testing
Introduction to Software Testing Chapter 2 Model-Driven Test Design
Introduction to Software Testing Chapter 9.2 Program-based Grammars
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Introduction to Software Testing Chapter 5.2 Program-based Grammars
Moonzoo Kim School of Computing KAIST
ISP Coverage Criteria CS 4501 / 6501 Software Testing
Graph Coverage for Source Code
Paul Ammann & Jeff Offutt
Graph Coverage Criteria
Software Testing Syntax-based Testing.
Paul Ammann & Jeff Offutt
Logic Coverage from Source Code
Graph Coverage Criteria
Mutation Testing The Mutants are Coming! Copyright © 2017 – Curt Hill.
Logic Coverage for Source Code CS 4501 / 6501 Software Testing
Introduction to Software Testing Chapter 5.1 Syntax-based Testing
Software Development Cycle
Mutation Testing Moonzoo Kim School of Computing KAIST
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Paul Ammann & Jeff Offutt
Software Testing and QA Theory and Practice (Chapter 5: Data Flow Testing) © Naik & Tripathy 1 Software Testing and Quality Assurance Theory and Practice.
Mutation Testing Faults are introduced into the program by creating many versions of the program called mutants. Each mutant contains a single fault. Test.
Presentation transcript:

Mutation Testing Moonzoo Kim School of Computing KAIST The original slides are taken from Chap. 9 of Intro. to SW Testing 2nd ed by Ammann and Offutt

Mutation Testing Operators modify a program under test to create mutant programs Mutant programs must compile correctly Mutants are not tests, but used to find good tests Once mutants are defined, tests must be found to cause mutants to fail when executed This is called “killing mutants” Most slides are taken from the text book “Introduction to Software Testing” by P.Ammann and J.Offutt

Killing Mutants 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. 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 Trivial mutant : Almost every test can kill it Equivalent mutant : No test can kill it (equivalent to original program) Stubborn mutant: Almost no test can kill it (a.k.a hard-to-kill mutants)

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 Replace one variable with another Changes operator Immediate runtime failure … if reached 6 mutants Each represents a separate program Immediate runtime failure if B==0 else does nothing

Syntax-Based Coverage Criteria Mutation Coverage (MC) : For each m  M, TR contains exactly one requirement, to kill m. The RIP model 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 …

Strong v.s. Weak Mutants 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

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

Strong Versus Weak Mutation 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 } Reachability : X < 0 Infection : X != 0 (X = -6) will kill mutant 4 under weak mutation Propagation : ((double) ((0-X)/2) == ((double) 0-X) / 2.0) != ((double) (0/2) == ((double) 0) / 2.0) That is, X is not even … Thus (X = -6) does not kill the mutant under strong mutation

Testing Programs with Mutation Input test method Create mutants Run equivalence detector Generate test cases Run T on P no Run mutants: schema-based weak selective Threshold reached ? Eliminate ineffective TCs P (T) correct ? yes Fix P no

Why Mutation Testing Works Fundamental Premise of Mutation Testing If the software contains a fault, there will usually be a set of mutants that can only be killed by a test case that also detects that fault Also known as “Coupling Effect” “a test data set that distinguishes all programs with simple faults is so sensitive that it will also distinguish programs with more complex faults” R. A. DeMillo, R. J. Lipton, and F. G. Sayward. Hints on test data selection: Help for the practicing programmer. Computer, 11(4), April 1978. 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 …

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 If tests that are created specifically to kill mutants created by a collection of mutation operators O = {o1, o2, …} also kill mutants created by all remaining mutation operators with very high probability, then O defines an effective set of mutation operators

Mutation Operators 1. ABS –– Absolute Value Insertion: Each arithmetic expression (and subexpression) is modified by the functions abs(), negAbs(), and failOnZero(). 1. ABS –– Absolute Value Insertion: Examples: a = m * (o + p); ∆1 a = abs (m * (o + p)); ∆2 a = m * abs ((o + p)); ∆3 a = failOnZero (m * (o + p)); 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: Examples: a = m * (o + p); ∆1 a = m + (o + p); ∆2 a = m * (o * p); ∆3 a = m leftOp (o + p);

3. ROR –– Relational Operator Replacement: 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) ∆1 if (X > Y) ∆2 if (X < Y) ∆3 if (X falseOp 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) ∆1 if (X <= Y || a > 0) ∆2 if (X <= Y leftOp a > 0) // returns result of left clause

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. Examples: byte b = (byte) 16; b = b >> 2; ∆1 b = b << 2; ∆2 b = b leftOp 2; // result is b 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: int a = 60; int b = 13; int c = a & b; ∆1 int c = a | b; ∆2 int c = a rightOp b; // result is b

7. ASR –– Assignment Operator Replacement: Each occurrence of one of the assignment operators (+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=) is replaced by each of the other operators. 7. ASR –– Assignment Operator Replacement: Examples: a = m * (o + p); ∆1 a += m * (o + p); ∆2 a *= m * (o + p); 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); ∆1 a = m * -(o + p); ∆2 a = -(m * (o + p));

9. UOD –– Unary Operator Deletion: Each unary operator (arithmetic +, arithmetic -, conditional !, logical~) is deleted. 9. UOD –– Unary Operator Deletion: Examples: if !(X <= Y && !Z) ∆1 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); ∆ 1 a = o * (o + p); ∆ 2 a = m * (m + p); ∆ 3 a = m * (o + o); ∆ 4 p = m * (o + p);

11. BSR –– Bomb Statement Replacement: Each statement is replaced by a special Bomb() function. Example: a = m * (o + p); ∆1 Bomb() // Raises exception when reached

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 All-defs data flow coverage Reference: An Analysis and Survey of the Development of Mutation Testing by Y.Jia et al. IEEE Transactions on Software Engineering Volume: 37 Issue: 5 Design Of Mutant Operators For The C Programming Language by H.Agrawal et al. Technical report

Bug Observability/Detection Model: Reachability, Infection, Propagation, and Revealation (RIPR) Terminology Fault: static defect in a program text (a.k.a a bug) Error: dynamic (intermediate) behavior that deviates from its (internal) intended goal A fault causes an error (i.e. error is a symptom of fault) Failiure: dynamic behavior which violates a ultimate goal of a target program Not every error leads to failure due to error masking or fault tolerance Graph coverage Test requirement satisfaction == Reachability the fault in the code has to be reached Logic coverage Test requirement satisfaction == Infection the fault has to put the program into an error state. Note that a program is in an error state does not mean that it will always produce the failure Mutation coverage Test requirement satisfaction == Propagation the program needs to exhibit incorrect outputs Furthermore, test oracle plays critical role to reveal failure of a target program (Revealation)