a, boolean b) { if (a && b) { return 42; } else { return 0; } } @Test public void testBothFalse() { int result = checkConditions(false, false); assertEquals(0, result); } @Test public void testBothTrue () { int result = checkConditions(true, true); assertEquals(42, result); } Coverage: 100% Usefulness: >0 But still wrong
a, boolean b) { if (a && b) { return 42; } else { return 0; } } @Test public void testBothFalse() { int result = checkConditions(false, false); assertEquals(0, result); } @Test public void testBothTrue () { int result = checkConditions(true, true); assertEquals(42, result); } Mutate
a, boolean b) { if (a || b) { return 42; } else { return 0; } } @Test public void testBothFalse() { int result = checkConditions(false, false); assertEquals(0, result); } @Test public void testBothTrue () { int result = checkConditions(true, true); assertEquals(42, result); } Passing tests
while (someCondition) { doStuff(); index++; if (index == 100) { break; } } int index = 0 while (someCondition) { doStuff(); index++; if (index >= 100) { break; } } Mutates to But the programs are equivalent, so no test will fail
– Ant – Maven • Bytecode level mutations (faster) • Very customisable – Exclude classes/packages from mutation – Choose which mutations you want – Timeouts • Makes pretty HTML reports (line/mutation coverage)
Runs in Rubinius (1.8 or 1.9 mode) • Only supports RSpec • Easy to set up rvm install rbx-head rvm use rbx-head gem install mutant • And easy to use mutate “ClassName#method_to_test” spec