Top Banner
© Computas AS 27.01.12 Mutation Testing Filip van Laenen OOP 2012 2012-01-24
79

Mutation testing (OOP 2012, 2012-JAN-24)

Oct 31, 2014

Download

Technology

My presentation about mutation testing at the OOP 2012 conference in Munich, Germany on 24 Januray 2012.

Notes:
* PIT now integrates with TestNG too
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Mutation testing (OOP 2012, 2012-JAN-24)

© Computas AS 27.01.12

Mutation Testing

Filip van LaenenOOP 2012

2012-01-24

Page 2: Mutation testing (OOP 2012, 2012-JAN-24)

2 © Computas AS 27.01.12

Agenda

• Basics of mutation testing• Relation to other testing techniques• Example• Mutation testing techniques• Mutation testing tools• Personal experiences and recommendations• Improvements• Questions and comments

Page 3: Mutation testing (OOP 2012, 2012-JAN-24)

3 © Computas AS 27.01.12

Basics ofMutation Testing

Page 4: Mutation testing (OOP 2012, 2012-JAN-24)

4 © Computas AS 27.01.12

Mutation Testing in a Nutshell

Seeking The Summoner @ The Daily WTFhttp://thedailywtf.com/Articles/Seeking-The-Summoner.aspx

Page 5: Mutation testing (OOP 2012, 2012-JAN-24)

5 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 6: Mutation testing (OOP 2012, 2012-JAN-24)

6 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 7: Mutation testing (OOP 2012, 2012-JAN-24)

7 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

• Unit tests guard the source code• But who guards the guardians?

• Do the unit tests cover all source code?• Lines?• Branches?• Paths?

• Do the unit tests test the right things?

Mutation testing tests the tests!

Page 8: Mutation testing (OOP 2012, 2012-JAN-24)

8 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 9: Mutation testing (OOP 2012, 2012-JAN-24)

9 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 10: Mutation testing (OOP 2012, 2012-JAN-24)

10 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 11: Mutation testing (OOP 2012, 2012-JAN-24)

11 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 12: Mutation testing (OOP 2012, 2012-JAN-24)

12 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 13: Mutation testing (OOP 2012, 2012-JAN-24)

13 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 14: Mutation testing (OOP 2012, 2012-JAN-24)

14 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

def max(a, b) { return (a < b) ? b : a;}

def max(a, b) { return (a ≤ b) ? b : a;}

Page 15: Mutation testing (OOP 2012, 2012-JAN-24)

15 © Computas AS 27.01.12

Mutation Testing in a Nutshell (cont'd)

Page 16: Mutation testing (OOP 2012, 2012-JAN-24)

16 © Computas AS 27.01.12

Does Mutation Testing Work?

In practice, 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.

Geist et. al., “Estimation and Enhancement of Real-time Software Reliability through Mutation Analysis,” 1992

Page 17: Mutation testing (OOP 2012, 2012-JAN-24)

17 © Computas AS 27.01.12

Does Mutation Testing Work? (cont'd)

Complex faults are coupled to simple faults in such a way that a test data set

that detects all simple faults in a program will detect most complex faults.

K. Wah, “Fault Coupling in Finite Bijective Functions,” 1995

Page 18: Mutation testing (OOP 2012, 2012-JAN-24)

18 © Computas AS 27.01.12

Does Mutation Testing Work? (cont'd)

• “Generated mutants are similar to real faults.”• Andrews, Briand, Labiche, ICSE 2005

• “Mutation testing is more powerful than statement or branch coverage.”• Walsh, Ph.D. Thesis, State University of New York at

Binghampton, 1985• “Mutation testing is superior to data flow

coverage criteria.”• Frankl, Weiss, Hu, Journal of Systems and Software,

1997

Page 19: Mutation testing (OOP 2012, 2012-JAN-24)

19 © Computas AS 27.01.12

Relation to OtherTesting Techniques

Page 20: Mutation testing (OOP 2012, 2012-JAN-24)

20 © Computas AS 27.01.12

Relation to Other Testing Techniques

• Unit tests• Test-Driven Development (TDD)• Test coverage• Static code analysis• Fuzz testing

Page 21: Mutation testing (OOP 2012, 2012-JAN-24)

21 © Computas AS 27.01.12

Relation to Other Testing Techniques

Page 22: Mutation testing (OOP 2012, 2012-JAN-24)

22 © Computas AS 27.01.12

Is Mutation Testing New?

• R. Lipton, “Fault Diagnosis of Computer Programs,” 1971

• R. Lipton et. al., “Hints on Test Data Selection: Help for the Practicing Programmer,” 1978

• Historical obstacles:• No unit testing• No TDD• Time-consuming• No integration with IDEs

Page 23: Mutation testing (OOP 2012, 2012-JAN-24)

23 © Computas AS 27.01.12

Practical Exampleof Mutation Testing

Page 24: Mutation testing (OOP 2012, 2012-JAN-24)

24 © Computas AS 27.01.12

Practical Example

# Returns the maximum of a.# @param a An array of integers.def max(a) { return …;}

Page 25: Mutation testing (OOP 2012, 2012-JAN-24)

25 © Computas AS 27.01.12

Practical Example (cont'd)

Omitted: max(null)Omitted: max([])

def max(a) { return …;}

Page 26: Mutation testing (OOP 2012, 2012-JAN-24)

26 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0

def max(a) { return 0;}

Page 27: Mutation testing (OOP 2012, 2012-JAN-24)

27 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1

def max(a) { return 0;}

Page 28: Mutation testing (OOP 2012, 2012-JAN-24)

28 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1

def max(a) { return a.first;}

Page 29: Mutation testing (OOP 2012, 2012-JAN-24)

29 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { return a.first;}

Page 30: Mutation testing (OOP 2012, 2012-JAN-24)

30 © Computas AS 27.01.12

Practical Example (cont'd)

Unit tests!

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { m ← a.first; foreach (e ∈ a) if (e > m) m ← e; return m;}

100% line coverage!

100% branch coverage?

Page 31: Mutation testing (OOP 2012, 2012-JAN-24)

31 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { m ← a.first; foreach (e ∈ a) if (e > m) m ← e; return m;}

Page 32: Mutation testing (OOP 2012, 2012-JAN-24)

32 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { m ← a.first; foreach (e ∈ a) if (true) m ← e; return m;}

Page 33: Mutation testing (OOP 2012, 2012-JAN-24)

33 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { return a.last;}

Page 34: Mutation testing (OOP 2012, 2012-JAN-24)

34 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2Assertion: max([2, 1]) = 2

def max(a) { return a.last;}

Page 35: Mutation testing (OOP 2012, 2012-JAN-24)

35 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2Assertion: max([2, 1]) = 2

def max(a) { m ← a.first; foreach (e ∈ a) if (e > m) m ← e; return m;}

Page 36: Mutation testing (OOP 2012, 2012-JAN-24)

36 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2Assertion: max([2, 1]) = 2

def max(a) { m ← -∞; foreach (e ∈ a) if (e > m) m ← e; return m;}

Page 37: Mutation testing (OOP 2012, 2012-JAN-24)

37 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { m ← a.first; foreach (e ∈ a) if (e > m) Implicit ← else-branch! m ← e; return m;}

Page 38: Mutation testing (OOP 2012, 2012-JAN-24)

38 © Computas AS 27.01.12

Practical Example (cont'd)

Assertion: max([0]) = 0Assertion: max([1]) = 1Assertion: max([1, 2]) = 2

def max(a) { m ← -∞; foreach (e ∈ a) if (e > m) Implicit ← else-branch! m ← e; return m;}

100% branch coverage?

Page 39: Mutation testing (OOP 2012, 2012-JAN-24)

39 © Computas AS 27.01.12

Practical Example (cont'd)

• 100% test coverage may be illusory• Line coverage• Branch coverage• Path coverage

• TDD principles easily broken• Even if you're very careful

Page 40: Mutation testing (OOP 2012, 2012-JAN-24)

40 © Computas AS 27.01.12

Mutation TestingTechniques

Page 41: Mutation testing (OOP 2012, 2012-JAN-24)

41 © Computas AS 27.01.12

Mutation Testing Techniques

• Three aspects:• Mutation injection• Mutation types• Unit test selection per mutant

• Key properties:• Efficiency• Performance

Page 42: Mutation testing (OOP 2012, 2012-JAN-24)

42 © Computas AS 27.01.12

Mutation Injection

• Source code mutation• Binary code mutation• Caveats:

• De-mutation• Compilation errors• Invalid binary code

Page 43: Mutation testing (OOP 2012, 2012-JAN-24)

43 © Computas AS 27.01.12

Mutation Types

• Some mutations never change behaviour• Constants reused by unit tests• Log messages

• Some mutations can change behaviour• Switching between < and ≠• Switching between < and ≤

• Some mutations always change behaviour• Switching between < and ≥

Page 44: Mutation testing (OOP 2012, 2012-JAN-24)

44 © Computas AS 27.01.12

Mutation Types (cont'd)

def max(a, b) { return (a < b) ? b : a;}

def max(a, b) { return (a ≤ b) ? b : a;}

def max(a, b) { return (a ≥ b) ? b : a;}

Page 45: Mutation testing (OOP 2012, 2012-JAN-24)

45 © Computas AS 27.01.12

Mutation Types (cont'd)

for (i ← 0; i < 10; i++) …

for (i ← 0; i ≠ 10; i++) …

for (i ← 0; i ≥ 10; i++) …

Page 46: Mutation testing (OOP 2012, 2012-JAN-24)

46 © Computas AS 27.01.12

Mutation Types Guaranteed to Change Behaviour

• Negation of the comparison• Switching between = and ≠• Switching between < and ≥• Switching between > and ≤

• Negation of boolean conditions• Adding a ¬, ! or ~

• Shortcutting boolean conditions• Replacement with True or False

*

Page 47: Mutation testing (OOP 2012, 2012-JAN-24)

47 © Computas AS 27.01.12

Unit Test Selection

• Goal: find the unit test that “kills” the mutant• Selection aids:

• Hints• Name/package matching• Code coverage tools• Automatic learning• Other heuristics

Page 48: Mutation testing (OOP 2012, 2012-JAN-24)

48 © Computas AS 27.01.12

Unit Test Selection (cont'd)

• System:• 50 classes• 20 unit tests per class• 1 ms per unit test• Unit testing time: 50 × 20 × 1ms = 1s

• 10 mutants per class:• Brute-force: 10 × 50 × 1s = 6m 20s• Educated: 10 × 50 × 20 × 1ms = 10s

Page 49: Mutation testing (OOP 2012, 2012-JAN-24)

49 © Computas AS 27.01.12

Unit Test Selection (cont'd)

• System:• 500 classes• 20 unit tests per class• 1 ms per unit test• Unit testing time: 500 × 20 × 1ms = 10s

• 10 mutants per class:• Brute-force: 10 × 500 × 10s = 13h 53m 20s• Educated: 10 × 500 × 20 × 1ms = 1m 40s

Page 50: Mutation testing (OOP 2012, 2012-JAN-24)

50 © Computas AS 27.01.12

Complexity

• f: Number of function points• φ: Number of function points per class, ≥ 1• τ: Number of unit tests per function point, ≥ 1• μ: Number of mutants per function point, ≥ 1

• Brute-force: (f × τ) × (f × μ) = τ × μ × f²• Educated force: τ × μ × φ × f• Ideal: τ × μ × f

Page 51: Mutation testing (OOP 2012, 2012-JAN-24)

51 © Computas AS 27.01.12

Complexity (cont'd)

• c: Number of classes• φ: Number of function points per class, ≥ 1• τ: Number of unit tests per function point, ≥ 1• μ: Number of mutants per function point, ≥ 1

• Brute-force: (f × τ) × (f × μ) = τ × μ × φ² × c²• Educated force: τ × μ × φ² × c• Ideal: τ × μ × φ × c

Page 52: Mutation testing (OOP 2012, 2012-JAN-24)

52 © Computas AS 27.01.12

Loops

for (i ← 0; i < 10; i++) …

for (i ← 0; i < 10; i--) …

Page 53: Mutation testing (OOP 2012, 2012-JAN-24)

53 © Computas AS 27.01.12

Infinite Loops

• Terminate mutants that take too long to run• What's too long?

• Ruins the performance• Can be hard to predict

Page 54: Mutation testing (OOP 2012, 2012-JAN-24)

54 © Computas AS 27.01.12

Other Problems

• Recursion:• Stack overflows• Out of memory exceptions

• Syntax errors• Segmentation faults

Page 55: Mutation testing (OOP 2012, 2012-JAN-24)

55 © Computas AS 27.01.12

Mutation TestingTools

Page 56: Mutation testing (OOP 2012, 2012-JAN-24)

56 © Computas AS 27.01.12

Mutation Testing Tools

• Ruby: Heckle• Java:

• Jester• Jumble• PIT

• C#: Nester• Python: Pester

Page 57: Mutation testing (OOP 2012, 2012-JAN-24)

57 © Computas AS 27.01.12

Heckle

• Ruby• Test::Unit and rSpec• Usually run from the command-line• Runs a set of unit tests on a class or a method• Good to-the-point reporting• Good performance• Virtually no documentation

• http://rubyforge.org/projects/seattlerb/• http://docs.seattlerb.org/heckle/

Page 58: Mutation testing (OOP 2012, 2012-JAN-24)

58 © Computas AS 27.01.12

Heckle Mutations

• Booleans• Numbers• Strings• Symbols• Ranges• Regexes• Branches (if, while, unless, until)

Page 59: Mutation testing (OOP 2012, 2012-JAN-24)

59 © Computas AS 27.01.12

Heckle Sample Output

Initial tests pass. Let's rumble.******************************************************************** Greeter#greet loaded with 3 possible mutations*****************************************************************

3 mutations remaining...2 mutations remaining...1 mutations remaining...No mutants survived. Cool!

Page 60: Mutation testing (OOP 2012, 2012-JAN-24)

60 © Computas AS 27.01.12

My Heckle Sample Output

filip@filip-laptop:~/github/wruf$ rake heckle(in /home/filip/github/wruf)Doing mutation testing on 15 method(s) of FlickrSearcher against test/flickr_searcher_unit_test.rb: o FlickrSearcher#convert_photo_info [1/15] o FlickrSearcher#create_form_data_to_get_info_about_photo [2/15] o FlickrSearcher#create_form_data_to_get_info_about_user [3/15] o FlickrSearcher#create_form_data_to_search_photos [4/15] o FlickrSearcher#do_rest_request [5/15] o FlickrSearcher#get_author [6/15]… o FlickrSearcher#get_photo_info [12/15] o FlickrSearcher#get_photo_url [13/15] o FlickrSearcher#get_ref_url [14/15] o FlickrSearcher#get_ref_url_from_xml_photo_info [15/15]Checked 192 mutations, and no issues were found in FlickrSearcher.

Page 61: Mutation testing (OOP 2012, 2012-JAN-24)

61 © Computas AS 27.01.12

My Heckle Sample Output (cont'd)

Doing mutation testing on 7 method(s) of WrufSettings against test/wruf_settings_unit_test.rb: o WrufSettings#dimensions [1/7] o WrufSettings#dimensions= [2/7] o WrufSettings#hours [3/7] o WrufSettings#hours= [4/7] o WrufSettings#tags [5/7] o WrufSettings#tolerance [6/7] o WrufSettings#tolerance= [7/7]Checked 0 mutations, and no issues were found in WrufSettings.

Page 62: Mutation testing (OOP 2012, 2012-JAN-24)

62 © Computas AS 27.01.12

Heckle Sample Report

--- original+++ mutation def calculate_precision(rescaled_number) if (rescaled_number < 9.995) then return 2 else if (rescaled_number < 99.95) then return 1 else if (rescaled_number >= 99.95) then return 0 else- return -1+ return -70 end end end end

Page 63: Mutation testing (OOP 2012, 2012-JAN-24)

63 © Computas AS 27.01.12

Jester

• Java• JUnit• Usually run from the command-line

• Grester for Maven2• Operates on source code• Runs all unit tests on all classes• Reporting and documentation could be better

• http://jester.sourceforge.net/• http://sourceforge.net/projects/grester/

Page 64: Mutation testing (OOP 2012, 2012-JAN-24)

64 © Computas AS 27.01.12

Jester Sample Report Overview

Page 65: Mutation testing (OOP 2012, 2012-JAN-24)

65 © Computas AS 27.01.12

Jester Sample Detailed Report

Page 66: Mutation testing (OOP 2012, 2012-JAN-24)

66 © Computas AS 27.01.12

Pester and Nester

• Pester• Jester for Python• PyUnit

• Nester• Port of Jester for C#• NUnit• Integrated with Visual Studio• But outdated…• http://nester.sourceforge.net/

Page 67: Mutation testing (OOP 2012, 2012-JAN-24)

67 © Computas AS 27.01.12

Nester Sample Report

Page 68: Mutation testing (OOP 2012, 2012-JAN-24)

68 © Computas AS 27.01.12

Jumble

• Java• JUnit• Run from the command-line• Operates on byte code• Runs unit tests on a class• Reporting and documentation could be better• Claims to be faster than Jester

• http://jumble.sourceforge.net/index.html

Page 69: Mutation testing (OOP 2012, 2012-JAN-24)

69 © Computas AS 27.01.12

Jumble Sample Report

Mutating FooTests: FooTestMutation points = 12, unit test time limit 2.02s..M FAIL: Foo:31: negated conditionalM FAIL: Foo:33: negated conditionalM FAIL: Foo:34: - -> +M FAIL: Foo:35: negated conditional......Score: 67%

Page 70: Mutation testing (OOP 2012, 2012-JAN-24)

70 © Computas AS 27.01.12

PIT

• Java• JUnit• Maven or command-line• Operates on byte code• Large set of mutators

• Also possibly equivalent mutators available• Highly configurable• Sensible defaults

• http://pitest.org/

Page 71: Mutation testing (OOP 2012, 2012-JAN-24)

71 © Computas AS 27.01.12

PIT Mutators

• Conditionals Boundary• Negate Conditionals• Math• Increments• Invert Negatives• Inline Constant*• Return Values• Void Method Call• Non Void Method Call*• Constructor Call*

Page 72: Mutation testing (OOP 2012, 2012-JAN-24)

72 © Computas AS 27.01.12

PIT Sample Report

Page 73: Mutation testing (OOP 2012, 2012-JAN-24)

73 © Computas AS 27.01.12

Personal Experiencesand Recommendations

Page 74: Mutation testing (OOP 2012, 2012-JAN-24)

74 © Computas AS 27.01.12

Experiences and Recommendations

• Use mutation testing from day 1• Start on a small code base

• Keep number of unit tests per class low• Have small classes

• Select a good tool• Configurable• Flexible• One that can output the mutant

Page 75: Mutation testing (OOP 2012, 2012-JAN-24)

75 © Computas AS 27.01.12

Experiences and Recommendations (cont'd)

• Believe the tool• Or try to proof that the tool is wrong

• Fix the problem• Don't turn mutation testing off

• Embrace the “more than 100%” test coverage• Path coverage• Less code• More unit tests• More intelligent unit tests

Page 76: Mutation testing (OOP 2012, 2012-JAN-24)

76 © Computas AS 27.01.12

Improvements

Page 77: Mutation testing (OOP 2012, 2012-JAN-24)

77 © Computas AS 27.01.12

Improvements

• Integration with more unit testing frameworks• Better unit test–source code mapping

• Better heuristics• Parallellisation• Better reporting• IDE integration• Building tool integration

Page 78: Mutation testing (OOP 2012, 2012-JAN-24)

78 © Computas AS 27.01.12

The Ideal Mutation Testing Tool™

• Easy integration with building tools• Easy integration with IDEs• Support for all unit testing frameworks• Human-aided unit test selection heuristics• Full parallellisation• Good source code mutation reporting

Page 79: Mutation testing (OOP 2012, 2012-JAN-24)

79 © Computas AS 27.01.12

Questions?

Computas ASLysaker Torg 45, pb 482N-1327 LysakerNORWAY

Tel +47-67 83 10 00Fax +47-67 83 10 01Org.nr: NO 986 352 325 MVAwww.computas.com

Contact:

[email protected] @filipvanlaenen