mutasjonstesting – lag bugs for å få bedre kode

72
MUTASJONSTESTING LAG BUGS FOR Å FÅ BEDRE KODE Filip van Laenen — Testdagen Odin 2015 1 https://www.flickr.com/photos/cskk/3759544397

Upload: filip-van-laenen

Post on 23-Jan-2017

287 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Mutasjonstesting – Lag bugs for å få bedre kode

MUTASJONSTESTING

LAG BUGS FOR Å FÅ BEDRE KODEFilip van Laenen — Testdagen Odin 2015

1https://www.flickr.com/photos/cskk/3759544397

Page 2: Mutasjonstesting – Lag bugs for å få bedre kode

Hvem er jeg?

2

● 18 år i IT-bransjen– Utvikler (Java/Smalltalk/Ruby)

– Arkitekt/teknisk ansvarlig

– (Tester/QA)

● Flere års erfaring med mutasjonstesting

http://www.slideshare.net/filipvanlaenen/

Page 3: Mutasjonstesting – Lag bugs for å få bedre kode

Mutation Testing – The Book

https://leanpub.com/mutationtesting

3

Page 4: Mutasjonstesting – Lag bugs for å få bedre kode

Mutation Testing – The Book

https://leanpub.com/mutationtesting

4

$0.00

SJEKK PRISEN!

Page 5: Mutasjonstesting – Lag bugs for å få bedre kode

HVA ER MUTASJONSTESTING?

5https://www.flickr.com/photos/cskk/3759544397

Page 6: Mutasjonstesting – Lag bugs for å få bedre kode

6http://thedailywtf.com/Articles/Seeking-The-Summoner.aspx

Page 7: Mutasjonstesting – Lag bugs for å få bedre kode

7

Page 8: Mutasjonstesting – Lag bugs for å få bedre kode

8

Page 9: Mutasjonstesting – Lag bugs for å få bedre kode

9

Page 10: Mutasjonstesting – Lag bugs for å få bedre kode

Mutasjonen i kildekoden

10

int max(int a, int b) { return (a < b) ? b : a;}

int max(int a, int b) { return (a ≥ b) ? b : a;}

Page 11: Mutasjonstesting – Lag bugs for å få bedre kode

11

Page 12: Mutasjonstesting – Lag bugs for å få bedre kode

12

Page 13: Mutasjonstesting – Lag bugs for å få bedre kode

13

Page 14: Mutasjonstesting – Lag bugs for å få bedre kode

14

Page 15: Mutasjonstesting – Lag bugs for å få bedre kode

Ekvivalente mutasjoner

15

int max(int a, int b) { return (a < b) ? b : a;}

int max(int a, int b) { return (a ≤ b) ? b : a;}

Page 16: Mutasjonstesting – Lag bugs for å få bedre kode

MUTASJONSOPERATORER

16https://www.flickr.com/photos/cskk/3759544397

Page 17: Mutasjonstesting – Lag bugs for å få bedre kode

Mutasjonsoperatorer

17

● Aritmetikk (+, -, ×, ÷, …)

● Boolske operatorer ( , , ¬, …)∧ ∨

● Sammenligninger (=, <, >, ≤, ≥, ≠, …)

● Kortslutning av grener

● Konstanter (tall, tekst, …)

● Fjerning av linjer

● Nullstilling av returverdier

https://www.flickr.com/photos/ynse/1531699476/

Page 18: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel

18

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade > 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 19: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: ≥ → >

19

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade > 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 20: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: + → -

20

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed - 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 21: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: endring av tallverdi

21

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 13) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 22: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: kortslutning av if-løkke

22

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (true) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 23: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: kortslutning av if-løkke

23

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (true) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 24: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: fjerning av en kodelinje

24

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 25: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: nullstilling av returverdi

25

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return 0;}

https://www.flickr.com/photos/ynse/1531699476/

Page 26: Mutasjonstesting – Lag bugs for å få bedre kode

Mutasjonsoperatorer

26

● Regulære uttrykk

● Samtidighet

● Avhengigheter

● API-endringer

● Arv

● …

https://www.flickr.com/photos/ynse/1531699476/

Page 27: Mutasjonstesting – Lag bugs for å få bedre kode

Utfordringer

27

● Evige løkker/rekursjon

● Syntaksfeil

● Tilstandslekkasje

● Segmentation faults

● Ekvivalente mutasjoner

https://www.flickr.com/photos/ynse/1531699476/

Page 28: Mutasjonstesting – Lag bugs for å få bedre kode

Ekvivalente mutasjoner

● To forskjellige systemer som alltid gir samme output for samme input

● Vanskelig å oppdage automatisk● Vanskelig å verifisere manuelt

28https://www.flickr.com/photos/cq-biker/15606327367/

Page 29: Mutasjonstesting – Lag bugs for å få bedre kode

Ekvivalente mutasjoner

number max(a, b) {

if (a ≥ b) {

return a;

} else {

return b;

}

}

number max(a, b) {

if (a > b) {

return a;

} else {

return b;

}

}

29https://www.flickr.com/photos/cq-biker/15606327367/

Page 30: Mutasjonstesting – Lag bugs for å få bedre kode

Ekvivalente mutasjoner

number max(a, b) {

if (a ≥ b) {

return a;

} else {

return b;

}

}

number max(a, b) {

if (a > b) {

return a;

} else {

return b;

}

}

30https://www.flickr.com/photos/cq-biker/15606327367/

Page 31: Mutasjonstesting – Lag bugs for å få bedre kode

HVORFOR VIRKER MUTASJONSTESTING?

31https://www.flickr.com/photos/cskk/3759544397

Page 32: Mutasjonstesting – Lag bugs for å få bedre kode

“Hvorfor virker mutasjonstesting?

32

Generated mutants are similar to real faults.

Andrews, Briand, Labiche, ICSE 2005

Page 33: Mutasjonstesting – Lag bugs for å få bedre kode

“Hvorfor virker mutasjonstesting?

33

In practice, if the software contains a fault, there will usually be a set of mutants that can only be killed by a test case that also detects that fault.

Geist et. al., “Estimation and Enhancement of Real-time Software Reliability through Mutation Analysis,” 1992

Page 34: Mutasjonstesting – Lag bugs for å få bedre kode

“Hvorfor virker mutasjonstesting?

34

Complex faults are coupled to simple faults in such a way that a test data set that detects all simple faults in a program will detect most complex faults.

K. Wah, “Fault Coupling in Finite Bijective Functions,” 1995

Page 35: Mutasjonstesting – Lag bugs for å få bedre kode

“Hvorfor virker mutasjonstesting?

35

Complex faults are coupled to simple faults in such a way that a test data set that detects all simple faults in a program will detect most complex faults.

K. Wah, “Fault Coupling in Finite Bijective Functions,” 1995

Page 36: Mutasjonstesting – Lag bugs for å få bedre kode

““

Virker mutasjonstesting?

36

Mutation testing is more powerful than statement or branch coverage.

Walsh, Ph.D. Thesis, State University of New York at Binghampton, 1985

Mutation testing is superior to data flow coverage criteria.

Frankl, Weiss, Hu, Journal of Systems and Software, 1997

Page 37: Mutasjonstesting – Lag bugs for å få bedre kode

MUTASONSTESTING OG TESTING

37https://www.flickr.com/photos/cskk/3759544397

Page 38: Mutasjonstesting – Lag bugs for å få bedre kode

Testdekning

● Vanskelig å jukse– Å kjøre gjennom kildekoden

er ikke nok

● Kan peke ut fokusområder for

manuell testing

38

Page 39: Mutasjonstesting – Lag bugs for å få bedre kode

Manglende testtilfeller

39

● Tips til nye testtilfeller

– Avhengig av verktøyet

– Krever tilgang til rapportene

– Ikke alltid trivielt

http://www.javaadvent.com/2014/12/mutation-testing-in-java-with-pit-and.html

Page 40: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel

40

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade > 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

Page 41: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: ≥ → >

41

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade > 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en 12 i testsettet ditt

Page 42: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: + → -

42

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed - 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en ≥12 i testsettet ditt

Page 43: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: endring av tallverdi

43

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 13) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en 12 i testsettet ditt

Page 44: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: kortslutning av if-løkke

44

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (true) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en <12 i testsettet ditt

Page 45: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: fjerning av en kodelinje

45

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en ≥12 i testsettet ditt

Page 46: Mutasjonstesting – Lag bugs for å få bedre kode

Eksempel: nullstilling av returverdi

46

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return passed;}

integer students_passed(grades) { passed ← 0; foreach (grade ∈ grades) { if (grade ≥ 12) { passed ← passed + 1 } } return 0;}

https://www.flickr.com/photos/ynse/1531699476/

⇒ Ha en ≥12 i testsettet ditt

Page 47: Mutasjonstesting – Lag bugs for å få bedre kode

HVIS MUTASJONSTESTING ER SÅ BRA,

HVORFOR BLIR DET IKKE BRUKT?

47https://www.flickr.com/photos/cskk/3759544397

Page 48: Mutasjonstesting – Lag bugs for å få bedre kode

Mutasjonstesting er gammelt nytt

● Allerede beskrevet i 1971:– R. Lipton, “Fault Diagnosis

of Computer Programs”

● Videre forskning i løpet av 1970-tallet:

– R. Lipton et. al., “Hints on Test Data Selection: Help for the Practicing Programmer,” 1978

48

Page 49: Mutasjonstesting – Lag bugs for å få bedre kode

Historiske hindringer

● Mangel på enhetstestingverktøy

● Mangel på enhetstestingpraksis

– TDD

● Ineffektive implementasjoner

– Lange prosesseringstider

● Integrasjon med utviklingsverktøy

49

Page 50: Mutasjonstesting – Lag bugs for å få bedre kode

50

Page 51: Mutasjonstesting – Lag bugs for å få bedre kode

YTELSE

51https://www.flickr.com/photos/cskk/3759544397

Page 52: Mutasjonstesting – Lag bugs for å få bedre kode

Kildekode eller binærkode?

● Kildekode– Tekstmanipulasjon

– Krever kompilering

● Binærkode– Raskt

– Krever dekompilering

● AST-tre– Gylden middelvei?

52https://www.flickr.com/photos/grant_subaru/9306928331

Page 53: Mutasjonstesting – Lag bugs for å få bedre kode

Utvelgelse av enhetstester

● Mål: finne enhetstesten som «dreper» mutanten

53https://www.flickr.com/photos/grant_subaru/9306928331

Page 54: Mutasjonstesting – Lag bugs for å få bedre kode

54

Page 55: Mutasjonstesting – Lag bugs for å få bedre kode

55

Page 56: Mutasjonstesting – Lag bugs for å få bedre kode

56

Page 57: Mutasjonstesting – Lag bugs for å få bedre kode

Utvelgelse av enhetstester

● Mål: finne enhetstesten som «dreper» mutanten

● Midler:– Testdekning

– Manuelle hints

– Konvensjoner (klassenavn, pakkenavn)

– Caching av testresultater

57https://www.flickr.com/photos/grant_subaru/9306928331

Page 58: Mutasjonstesting – Lag bugs for å få bedre kode

Kompleksitet

● Eksempel:– 50 klasser

– 20 enhetstester per klasse

– 1ms per enhetstest

– Testrunde: 50 × 20 × 1ms = 1s

● 100 mutanter per klasse:

– Naiv implementasjon: 100 × 50 × 1s = 1h 23m 20s

– Klassescoping: 100 × 50 × 20 × 1 ms = 1m 40s

– Idealt: 100 × 50 × 1ms = 5s

58https://www.flickr.com/photos/grant_subaru/9306928331

Page 59: Mutasjonstesting – Lag bugs for å få bedre kode

Kompleksitet

● Eksempel:– 500 klasser

– 20 enhetstester per klasse

– 1ms per enhetstest

– Testrunde: 500 × 20 × 1ms = 10s

● 100 mutanter per klasse:

– Naiv implementasjon: 100 × 500 × 10s = 5,8d

– Klassescoping: 100 × 500 × 20 × 1 ms = 16m 40s

– Idealt: 100 × 500 × 1ms = 50s

59https://www.flickr.com/photos/grant_subaru/9306928331

Page 60: Mutasjonstesting – Lag bugs for å få bedre kode

VERKTØY

60https://www.flickr.com/photos/cskk/3759544397

Page 61: Mutasjonstesting – Lag bugs for å få bedre kode

Anbefalte verktøy

● Java:– PIT

● Ruby:– Mutant

● PHP:

– Humbug

● JavaScript:– Grunt-mutation-testing

61https://www.flickr.com/photos/ianturk/18577725240/

Page 62: Mutasjonstesting – Lag bugs for å få bedre kode

PIT

62

● Java

● JUnit & TestNG

● Maven & kommandolinje

● Muterer bytekode

● Konfigurerbart sett med mutatorer

http://pitest.org/

Page 63: Mutasjonstesting – Lag bugs for å få bedre kode

PIT

63

● Java

● JUnit & TestNG

● Maven & kommandolinje

● Muterer bytekode

● Konfigurerbart sett med mutatorer

http://pitest.org/

http://www.javaadvent.com/2014/12/mutation-testing-in-java-with-pit-and.html

Page 64: Mutasjonstesting – Lag bugs for å få bedre kode

PIT

64

● Java

● JUnit & TestNG

● Maven & kommandolinje

● Muterer bytekode

● Konfigurerbart sett med mutatorer

http://pitest.org/

http://www.javaadvent.com/2014/12/mutation-testing-in-java-with-pit-and.html

Page 65: Mutasjonstesting – Lag bugs for å få bedre kode

Mutant

● Ruby

● Rspec

● Kommandolinje

● Aktivt prosjekt

● Grei dokumentasjon

https://github.com/mbj/mutant

65https://www.youtube.com/watch?v=awVUqUxhx8M

Page 66: Mutasjonstesting – Lag bugs for å få bedre kode

HVORDAN KOMME I GANG?

66https://www.flickr.com/photos/cskk/3759544397

Page 67: Mutasjonstesting – Lag bugs for å få bedre kode

Hvordan komme i gang

● Velg riktig verktøy

● Om mulig, bruk fra dag 1

● Avgrens i begynnelsen– Kritisk kode

– Relevante mutatorer

● Lær å bruke verktøyet

– Tro på hva det sier

– Eller bevis at det tar feil67

Page 68: Mutasjonstesting – Lag bugs for å få bedre kode

OPPSUMMERING

68https://www.flickr.com/photos/cskk/3759544397

Page 69: Mutasjonstesting – Lag bugs for å få bedre kode

Er mutasjonstesting nyttig?

69

● Enkle prinsipper

● Veldig kraftig verktøy

● Utfordringer rundt ytelse

● Verktøyene blir bedre og bedre

Ja , forutsatt at enhetstesting er på plass

Page 70: Mutasjonstesting – Lag bugs for å få bedre kode

Er mutasjonstesting nyttig?

70

● Enkle prinsipper

● Veldig kraftig verktøy

● Utfordringer rundt ytelse

● Verktøyene blir bedre og bedre

Ja , forutsatt at enhetstesting er på plass

Page 71: Mutasjonstesting – Lag bugs for å få bedre kode

Er mutasjonstesting nyttig?

71

● Enkle prinsipper

● Veldig kraftig verktøy

● Utfordringer rundt ytelse

● Verktøyene blir bedre og bedre

Ja , forutsatt at enhetstesting er på plass

Page 72: Mutasjonstesting – Lag bugs for å få bedre kode

Takk for din oppmerksomhet!

72

Contact information:

@filipvanlaenen

[email protected] / [email protected]

https://no.linkedin.com/in/filipvanlaenen

https://leanpub.com/mutationtesting http://www.slideshare.net/filipvanlaenen/