mutation testing in python - goto...

32
1 Mutation Testing in Python Austin Bingham @austin_bingham @sixty_north Sunday, October 4, 15

Upload: hoanghuong

Post on 12-Mar-2018

232 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

1

Mutation Testing in PythonAustin Bingham@austin_bingham

@sixty_north

Sunday, October 4, 15

Page 2: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

2Sunday, October 4, 15

Page 3: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

3Sunday, October 4, 15

Page 4: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

4

Mutation Testing

Sunday, October 4, 15

Page 5: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

What is mutation testing?

5

Code under test + test suite

Introduce single change to code under test

Run test suite

Ideally, all changes will result in test failures

Sunday, October 4, 15

Page 6: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

A nested loop of mutation and testing Basic algorithm

for operator in mutation-operators:

for site in operator.sites(code):

operator.mutate(site)

run_tests()

6Sunday, October 4, 15

Page 7: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

What does mutation testing tell us?

7

Killed

Tests properly detected the mutation.

Incompetent

Mutation produced code which is inherently flawed.

Survived

Tests failed to detect the mutant!

Tests are inadequate for detecting defects in necessary code

either

Mutated code is extraneous

or

Sunday, October 4, 15

Page 8: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

8Sunday, October 4, 15

Page 9: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Do my tests meaningfully cover my code's functionalityGoal #1: Coverage analysis

Is a line executed?versus

Is functionality verified?

9Sunday, October 4, 15

Page 10: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Survivors can indicate code which is no longer necessaryGoal #2: Detect unnecessary code

10Sunday, October 4, 15

Page 11: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Examples of mutations

11

• AOD - arithmetic operator deletion• AOR - arithmetic operator replacement• ASR - assignment operator replacement• BCR - break continue replacement• COD - conditional operator deletion• COI - conditional operator insertion• CRP - constant replacement• DDL - decorator deletion• EHD - exception handler deletion• EXS - exception swallowing• IHD - hiding variable deletion• IOD - overriding method deletion• IOP - overridden method calling position change• LCR - logical connector replacement• LOD - logical operator deletion• LOR - logical operator replacement• ROR - relational operator replacement• SCD - super calling deletion• SCI - super calling insert• SIR - slice index remove

Replace relational operatorx > 1

x < 1

break/continue replacementbreak

continue

Sunday, October 4, 15

Page 12: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Long test suites, large code bases, and many operators can add upComplexity #1: It takes a loooooooong time

12Image credit: John Mainstone (CC BY-SA 3.0)

What to do?‣Parallelize as much as possible!‣After baselining:

• only run tests on modified code• only mutate modified code‣Speed up test suite

Sunday, October 4, 15

Page 13: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Some incompetent mutants are harder to detect that othersComplexity #2: Incompetence detection

13

"Good luck with that."Alan Turing (apocryphal)

Sunday, October 4, 15

Page 14: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Some mutants have no detectable differences in functionalityComplexity #3: Equivalent mutants

14

def consume(iterator, n): """Advance the iterator n-steps ahead. If n is none, consume entirely."""

# Use functions that consume iterators at C speed. if n is None: # feed the entire iterator into a zero-length deque collections.deque(iterator, maxlen=0) else: # advance to the empty slice starting at position n next(islice(iterator, n, n), None)

Sunday, October 4, 15

Page 15: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

15

Cosmic Ray: Mutation Testing

for Python

Sunday, October 4, 15

Page 16: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Sub-packages and modules are discovered automaticallyCosmic Ray operates on packages

16

find_modules.py

def find_modules(name): module_names = [name] while module_names: module_name = module_names.pop() try: module = importlib.import_module(module_name) yield module if hasattr(module, '__path__'): for _, name, _ in pkgutil.iter_modules(module.__path__): module_names.append('{}.{}'.format(module_name, name)) except Exception: # pylint:disable=broad-except LOG.exception('Unable to import %s', module_name)

Sunday, October 4, 15

Page 17: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Support for tests systems are provided by dynamically discovered modulesTest system plugins

‣ Using OpenStack's stevedore plugin system

‣ Plugins can come from external packages

‣ Define a TestRunner subclass and implement the _run() method

• Report a simple success or failure along with a printable object containing more information

‣ TestRunners are only given a "start directory" as context

17

cosmic_ray

py.test

unittestplugins

my_package

my_test_system

Sunday, October 4, 15

Page 18: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Standard library abstract syntax tree handlingast

‣ Generate AST from source code

‣ Modify copies of ASTs using ast.NodeTransformer

18Sunday, October 4, 15

Page 19: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Operators are responsible for actual AST modification Operators

‣ Operators inherit from Operator which in turn inherits from ast.NodeTransformer

‣ Operators are provided as plugins‣ They have two primary jobs:

• Identify locations where a mutation can occur• Perform the mutation open request

19

+

1 2

operator

-

1 2

Sunday, October 4, 15

Page 20: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Converts unary-sub to unary-addExample operator: Reverse unary subtraction

20

class ReverseUnarySub(Operator): def visit_UnaryOp(self, node): if isinstance(node.op, ast.USub): return self.visit_mutation_site(node) else: return node

def mutate(self, node): node.op = ast.UAdd() return node

Sunday, October 4, 15

Page 21: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Python provides a sophisticated system for performing module importsModule management: overview

finders

Responsible for producing loaders when they recognize a module name

21

loaders

Responsible for populating module namespaces on import

sys.meta_path

A list of finders which are queried in order with module names when import is executed

Sunday, October 4, 15

Page 22: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Cosmic Ray implements a custom finderModule management: Finder

‣The finder associates module names with ASTs

‣ It produces loaders for those modules which are under mutation

22Sunday, October 4, 15

Page 23: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Cosmic Ray implements a custom finderModule management: Finder

23

class ASTFinder(MetaPathFinder): def __init__(self, fullname, ast): self._fullname = fullname self._ast = ast

def find_spec(self, fullname, path, target=None): if fullname == self._fullname: return ModuleSpec(fullname, ASTLoader(self._ast, fullname)) else: return None

Sunday, October 4, 15

Page 24: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Cosmic Ray implements a custom loaderModule management: Loader

‣The loader compiles its AST in the namespace of a new module object

24Sunday, October 4, 15

Page 25: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Cosmic Ray implements a custom loaderModule management: Loader

25

class ASTLoader: def __init__(self, ast, name): self._ast = ast self._name = name

def exec_module(self, mod): exec(compile(self._ast, self._name, 'exec'), mod.__dict__)

Sunday, October 4, 15

Page 26: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Mutant isolation with multiple processesmultiprocessing

26

cosmic-ray

Process 1

Mutant 1

Process 2

Mutant 2

Process 3

Mutant 3

‣ Avoid cross-mutant interference

‣ Significantly simplifies spawning processes

Sunday, October 4, 15

Page 27: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Actor model implementation in Pythonpykka

27

‣ Simplify design

‣ Support concurrency

Sunday, October 4, 15

Page 28: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Event loop to drive actorsasyncio

28Sunday, October 4, 15

Page 29: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Here's how we put all of these pieces togetherOperational overview

1. Find test-runner to use

2. Identify modules for mutation

3. Find all of the operators to use

4. Lazily generate a sequence of mutated ASTs

5. For each mutant, run the tests1.Each test runs in a new process

2.Each run manipulates its location sys.meta_path to inject the correct module29

Sunday, October 4, 15

Page 30: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

30

Demo

Sunday, October 4, 15

Page 31: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

Up to a two line subtitle, generally used to describe the takeaway for the slide

31Sunday, October 4, 15

Page 32: Mutation Testing in Python - GOTO Bloggotocon.com/.../slides/AustinBingham_MutationTestingInPython.pdf · Mutation Testing in Python Austin Bingham ... exception handler deletion

32

Thank you!

@sixty_north

Austin Bingham@austin_bingham

Sunday, October 4, 15