Mutation Testing
or who is going to test your tests ?
1st Developers@CERN Forum
Created by Sebastian Witowski
Do you write code ?
Do you test your code ?
Do you test your tests ?
Do you test the tests for your tests ?
Testing tests ?
Richard Lipton, Fault Diagnosis of Computer Programs, 1971
How does this mutation testing works ?
Step 1. Change you code in a small way:
- a + b ---> a * b
- a + 1 ---> a + 2
- a + b ---> a + c
- a + 1 ---> a + 1
a + 1
- (if a == 1 and b > 1) ---> (if a == 1 or b > 1)
Changes similar to small, programming errors.
Step 2. Run your tests
Step 2. Run your tests
Step 3. Get the mutation score
number or mutants killed
number of mutants created
Step 4. Profit
Example time
def multiply(a, b):
return a * b
def multiply(a, b):
return a * b
class CalculatorTest(TestCase):
def test_multiply(self):
self.assertEqual(multiply(2, 2), 4)
self.assertEqual(multiply(2, 2), 4)
↓
self.assertEqual(multiply(3, 3), 9)
Equivalent Mutant Problem
index = 0
while True:
do_stuff()
index = index + 1
if index == 10:
break
if index == 10:
vs.
if index >= 10:
Wrap up
The good parts
- Detect problems with your tests
- They discover dead code
- They are automatic
- How else would you test your tests ?
- (Semi-)Automatic tool for testing ? I'm in !
The not so good parts
- Mutation testing is slow:
(TIME = ALL MUTANTS x ALL TESTS)
- Handful of libraries
- Equivalent Mutant Problem
- Writing complex mutant tests is difficult
Mutant testing libraries
- Mutant - Ruby (last updated September 2015)
- VisualMutator - C# (last updated September 2015)
- Pitest - Java (last updated August 2015)
- Humbug - PHP (last updated May 2015)
- MuCheck - Haskell (last updated January 2015)
- MutPy - Python3 (last updated January 2014)
- Mutator - commercial solution for Java, Ruby, JavaScript and PHP
Example
MutPy (requires Python3)
calculator.py
def multiply(a, b):
return a * b
test_calculator.py
from unittest import TestCase
from calculator import multiply
class CalculatorTest(TestCase):
def test_multiply(self):
self.assertEqual(multiply(2, 2), 4)
self.assertEqual(multiply(2, 2), 4)
↓
self.assertEqual(multiply(3, 3), 9)
The future ?
Thank you !
Any questions ?
Happy coding testing !
This presentation is available on github, so you can see the slides on github pages
Mutation Testing
or who is going to test your tests ?
1st Developers@CERN Forum
Created by Sebastian Witowski