54
Can You Trust Your Tests? 2015 Vaidas Pilkauskas & Tadas Ščerbinskas

Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Embed Size (px)

Citation preview

Page 1: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

CanYou Trust Your Tests?

2015 Vaidas Pilkauskas & Tadas Ščerbinskas

Page 2: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Van Halen

Page 3: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Band Tour Rider

Page 4: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Van Halen’s 1982 Tour Rider

Page 5: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Page 6: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Agenda

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

Page 7: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Prod vs. Test code quality

Code has bugs.

Tests are code.

Tests have bugs.

Page 8: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Page 9: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Test quality

Readable

Focused

Concise

Well named

Page 10: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

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

show their absence!”- Edsger W. Dijkstra

Page 11: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Code Coverage

Page 12: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Types of Code Coverage

Lines

Branches

Instructions

Cyclomatic Complexity

Methods

& more

Page 13: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Page 14: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Lines

string foo() { return "a" + "b"}

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

Page 15: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Lines

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

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

Page 16: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Branches

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

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

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

Page 17: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

SUCCESS: 26/26 (100%) Tests passed

Page 18: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Can you trust 100% coverage?

Code coverage can only show what is not tested.

For interpreted languages 100% code coverage is kind of like full compilation.

Page 19: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Code Coverage can be gamed

On purpose or by accident

Page 20: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Mutation testing

Page 21: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Mutation testing

Changes your program code and expects your tests to fail.

Page 22: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

What exactly is a mutation?

def isFoo(a) { return a == foo}

def isFoo(a) { return a != foo}

def isFoo(a) { return true}

def isFoo(a) { return null}

>>>

Page 23: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Terminology

Applying a mutation to some code creates a mutant.

If test passes - mutant has survived.

If test fails - mutant is killed.

Page 24: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Failing is the new passing

Page 25: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

array = [a, b, c]

max(array) == ???

Page 26: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✘

Page 27: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔

// implementationmax(a) { return 0}

Page 28: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✘

// implementationmax(a) { return 0}

Page 29: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✔

// implementationmax(a) { return a.first}

Page 30: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✘

// implementationmax(a) { return a.first}

Page 31: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔

// implementationmax(a) { m = a.first for (e in a) if (e > m) m = e return m}

Page 32: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Coverage

Page 33: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Mutation// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔

// implementationmax(a) { m = a.first for (e in a) if (e > m) m = e return m}

Page 34: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Mutation// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔

// implementationmax(a) { m = a.first for (e in a) if (true) m = e return m}

Page 35: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔

// implementationmax(a) { return a.last}

Page 36: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔max([2, 1]) == 2 ✘

// implementationmax(a) { return a.last}

Page 37: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

// implementationmax(a) { m = a.first for (e in a) if (e > m) m = e return m}

// testmax([0]) == 0 ✔max([1]) == 1 ✔max([0, 2]) == 2 ✔max([2, 1]) == 2 ✔

Page 38: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Baby steps matter

Page 39: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Tests’ effectiveness is measured by number of killed mutants by

your test suite.

Page 40: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

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

Page 41: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

What if mutant survives

● Simplify your code● Add additional tests

● TDD - minimal amount of code to pass the test

Page 42: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Challenges

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

Page 43: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Equivalent mutations

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

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

Page 44: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Infinite Runtime

// Originalwhile (expression) doSomething();

// Mutantwhile (true) doSomething();

Page 45: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Disadvantages

● Can slow down your TDD rhythm

● May be very noisy

Page 46: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

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 really slow?

Let’s do 10 mutations per class● We get 3000 (300 * 10) mutations● runtime with all mutations is 150 minutes (3s * 3000)

Page 47: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

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 * 10 * 1 * 300 = 30s

Page 48: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Speeding it up

During development run tests that cover only your current changes

Page 49: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

● Continuous integration● TDD with mutation testing only

on new changes● Add mutation testing to your

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

Usage scenarios

Page 50: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Tools

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

languages

Page 51: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Summary

● Code coverage highlights code that is definitely not tested

● Mutation testing highlights code that definitely is tested

● Given non equivalent mutations, good test suite should work the same as a hash function

Page 52: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Vaidas Pilkauskas

@liucijus

● Vilnius JUG co-founder

● Vilnius Scala leader

● Coderetreat facilitator

● Mountain bicycle rider

● Snowboarder

About usTadas Ščerbinskas

@tadassce

● VilniusRB co-organizer

● RubyConfLT co-organizer

● RailsGirls Vilnius & Berlin coach

● Various board sports’ enthusiast

Page 53: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

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

Page 54: Can You Trust Your Tests? (Agile Tour 2015 Kaunas)

Q&A