Top Banner
Can You Trust Your Tests? 2016 Vaidas Pilkauskas & Tadas Ščerbinskas An Introduction to Mutation Testing
66

Can you trust your tests?

Jan 14, 2017

Download

Software

LatCraft
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: Can you trust your tests?

CanYou Trust Your Tests?

2016 Vaidas Pilkauskas & Tadas Ščerbinskas

An Introduction to Mutation Testing

Page 2: Can you trust your tests?

Thanks to co-author

Tadas ŠčerbinskasVilniusRB organizer

@tadassce

Page 3: Can you trust your tests?

Van Halen

Page 4: Can you trust your tests?

Band Tour Rider

Page 5: Can you trust your tests?

Van Halen’s 1982 Tour Rider

Page 6: Can you trust your tests?
Page 7: Can you trust your tests?

Agenda

1. Test quality & code coverage2. Mutation testing in theory3. Mutation testing in practice

Page 8: Can you trust your tests?

Prod vs. Test code quality

Code has bugs.

Tests are code.

Tests have bugs.

Page 9: Can you trust your tests?
Page 10: Can you trust your tests?
Page 11: Can you trust your tests?

Test quality

Readable

Focused

Concise

Well named

Page 12: Can you trust your tests?

“Program testing can be used to show the presence of bugs, but never to

show their absence!”- Edsger W. Dijkstra

Page 13: Can you trust your tests?

Code Coverage

Page 14: Can you trust your tests?

Types of Code Coverage

Lines

Branches

Instructions

Cyclomatic Complexity

Methods

& more

Page 15: Can you trust your tests?
Page 16: Can you trust your tests?

Lines

String foo() { return "a" + "b";}

assertThat(a.foo(), is("ab"))

Page 17: Can you trust your tests?

Lines

String foo(boolean arg) { return arg ? "a" : "b";}

assertThat(a.foo(true), is("a"));

Page 18: Can you trust your tests?

Branches

String foo(boolean arg) { return arg ? "a" : "b";}

assertThat(a.foo(true), is("a"));

assertThat(a.foo(false), is("b"));

Page 19: Can you trust your tests?

SUCCESS: 26/26 (100%) Tests passed

Page 20: Can you trust your tests?

Can you trust 100% coverage?

Code coverage can only show what is not tested.

For interpreted languages 100% code coverage is equivalent to compilation.

Page 21: Can you trust your tests?

Code Coverage can be gamed

On purpose or by accident

Page 22: Can you trust your tests?

Mutation testing

Page 23: Can you trust your tests?

Mutation testing

Changes your program code and expects your tests to fail.

Page 24: Can you trust your tests?

What exactly is a mutation?

Boolean isFoo(int a) { return a == foo;}

Boolean isFoo(int a) { return a != foo;}

Boolean isFoo(int a) { return true;}

Boolean isFoo(int a) { return null;}

>>>

Page 25: Can you trust your tests?

Terminology

Applying a mutation to some code creates a mutant.

If test passes - mutant has survived.

If test fails - mutant is killed.

Page 26: Can you trust your tests?

Failing is the new passing

Page 27: Can you trust your tests?

array = [a, b, c]

max(array) == ???

Page 28: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✘

Page 29: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✔

// implementationpublic static int of(int... integers) { return 0;}

Page 30: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✘

// implementationpublic static int of(int... integers) { return 0;}

Page 31: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔

// implementationpublic static int of(int... integers) { return integers[0];}

Page 32: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✘

// implementationpublic static int of(int... integers) { return integers[0];}

Page 33: Can you trust your tests?

// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔

// implementationpublic static int of(int... integers) { int max = integers[0]; for (int i : integers) if (max < i) max = i; return max;}

Page 34: Can you trust your tests?

Coverage

Page 35: Can you trust your tests?

Mutation// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔

// implementationpublic static int of(int... integers) { int max = integers[0]; for (int i : integers) if (max < i) max = i; return max;}

Page 36: Can you trust your tests?

Mutation// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔

// implementationpublic static int of(int... integers) { int max = integers[0]; for (int i : integers) if (true) max = i; return max;}

Page 37: Can you trust your tests?

Mutation// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔

// implementationpublic static int of(int... integers) { return integers[integers.length - 1];}

Page 38: Can you trust your tests?

Mutation// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔assertThat(Max.of(2, 1), equalTo(2)); ✘

// implementationpublic static int of(int... integers) { return integers[integers.length - 1];}

Page 39: Can you trust your tests?

Mutation// testassertThat(Max.of(0), equalTo(0)); ✔assertThat(Max.of(1), equalTo(1)); ✔assertThat(Max.of(1, 2), equalTo(2)); ✔assertThat(Max.of(2, 1), equalTo(2)); ✔

// implementationpublic static int of(int... integers) { int max = integers[0]; for (int i : integers) if (max < i) max = i; return max;}

Page 40: Can you trust your tests?

Baby steps matter

Page 41: Can you trust your tests?

Tests’ effectiveness is measured by number of killed mutants by

your test suite.

Page 42: Can you trust your tests?

It’s like hiring a white-hat hacker to try to break into your server and making sure you detect it.

Page 43: Can you trust your tests?

What if mutant survives

● Simplify your code● Add additional tests

● TDD - minimal amount of code to pass the test

Page 44: Can you trust your tests?

Challenges

1. High computation cost - slow2. Equivalent mutants - false negatives3. Infinite loops

Page 45: Can you trust your tests?

Equivalent mutations

// Originalint i = 0;while (i != 10) { doSomething(); i += 1;}

// Mutantint i = 0;while (i < 10) { doSomething(); i += 1;}

Page 46: Can you trust your tests?

Infinite Runtime

// Originalwhile (expression) doSomething();

// Mutantwhile (true) doSomething();

Page 47: Can you trust your tests?

● Let’s say we have codebase with:● 300 classes● around 10 tests per class● 1 test runs around 1ms● total test suite runtime is about 3s

Is it slow?

Let’s do 10 mutations per class● We get 3000 (300 classes * 10

mutations) mutations● runtime with all mutations is 150 minutes (3s * 3000)

Page 48: Can you trust your tests?

Speeding it up

Run only tests that cover the mutation● 300 classes● 10 tests per class● 10 mutations per class● 1ms test runtime● total mutation runtime

10 tests * 10 mutations * 1 ms * 300 classes = 30 s

Page 49: Can you trust your tests?

Speeding it up

During development run tests that cover only your current changes

Page 50: Can you trust your tests?

● Continuous integration● TDD with mutation testing only

on new changes● Add mutation testing to your

legacy project, but do not fail a build - produce a warning report

Usage scenarios

Page 51: Can you trust your tests?

Tools

● Ruby - Mutant● Java - PIT● And many tools for other

languages

Page 52: Can you trust your tests?

Pit● Active project● Good reporting● No Scala support :(

Page 53: Can you trust your tests?

Pit

PIT originally stood for Parallel Isolated Test.

Now it stands for PIT.

Page 54: Can you trust your tests?
Page 55: Can you trust your tests?

Test Selection

● Line coverage● Test execution speed● Test naming convention

Page 56: Can you trust your tests?

Running PIT

● Command line tool● Maven● Ant● Gradle

Page 57: Can you trust your tests?

PIT supports many mocking frameworks

● Mockito● EasyMock● JMock● PowerMock● JMockit

Page 58: Can you trust your tests?

Maven usage

mvn org.pitest:pitest-maven:mutationCoverage

With SCM plugin

mvn org.pitest:pitest-maven:scmMutationCoverage \

-Dinclude=ADDED,UNKNOWN -DmutationThreshold=85

Page 59: Can you trust your tests?

Configuration

● Dependency distance● Limit mutation number per class● Activate/deactivate mutators

● Extension points - Java SPI

Page 60: Can you trust your tests?

What about TDD?

● Influences code style● Helps to spot dead features● Puts emphasis on minimal code

to pass the test

Page 61: Can you trust your tests?

Summary

Code coverage highlights code that is not tested.

It shows which code you have executed in tests.

Page 62: Can you trust your tests?

Summary

Mutation testing highlights code that is tested.

It shows which code you have asserted in tests.

Page 63: Can you trust your tests?

How much we suck

Page 64: Can you trust your tests?

Vaidas Pilkauskas

@liucijus

● Vilnius JUG co-founder

● Vilnius Scala leader

● Coderetreat facilitator

● Mountain bicycle rider

● Snowboarder

About me

Page 65: Can you trust your tests?

Q&A

Page 66: Can you trust your tests?

Credits

A lot of presentation content is based on work by these guys

● Markus Schirp - author of Mutant● Henry Coles - author of PIT● Filip Van Laenen - working on a book