Mutasjonstesting – Lag bugs for å få bedre kode

Preview:

Citation preview

MUTASJONSTESTING

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

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

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/

Mutation Testing – The Book

https://leanpub.com/mutationtesting

3

Mutation Testing – The Book

https://leanpub.com/mutationtesting

4

$0.00

SJEKK PRISEN!

HVA ER MUTASJONSTESTING?

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

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

7

8

9

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;}

11

12

13

14

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;}

MUTASJONSOPERATORER

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

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/

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/

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/

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/

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/

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/

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/

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/

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/

Mutasjonsoperatorer

26

● Regulære uttrykk

● Samtidighet

● Avhengigheter

● API-endringer

● Arv

● …

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

Utfordringer

27

● Evige løkker/rekursjon

● Syntaksfeil

● Tilstandslekkasje

● Segmentation faults

● Ekvivalente mutasjoner

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

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/

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/

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/

HVORFOR VIRKER MUTASJONSTESTING?

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

“Hvorfor virker mutasjonstesting?

32

Generated mutants are similar to real faults.

Andrews, Briand, Labiche, ICSE 2005

“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

“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

“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

““

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

MUTASONSTESTING OG TESTING

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

Testdekning

● Vanskelig å jukse– Å kjøre gjennom kildekoden

er ikke nok

● Kan peke ut fokusområder for

manuell testing

38

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

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/

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

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

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

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

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

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

HVIS MUTASJONSTESTING ER SÅ BRA,

HVORFOR BLIR DET IKKE BRUKT?

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

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

Historiske hindringer

● Mangel på enhetstestingverktøy

● Mangel på enhetstestingpraksis

– TDD

● Ineffektive implementasjoner

– Lange prosesseringstider

● Integrasjon med utviklingsverktøy

49

50

YTELSE

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

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

Utvelgelse av enhetstester

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

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

54

55

56

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

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

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

VERKTØY

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

Anbefalte verktøy

● Java:– PIT

● Ruby:– Mutant

● PHP:

– Humbug

● JavaScript:– Grunt-mutation-testing

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

PIT

62

● Java

● JUnit & TestNG

● Maven & kommandolinje

● Muterer bytekode

● Konfigurerbart sett med mutatorer

http://pitest.org/

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

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

Mutant

● Ruby

● Rspec

● Kommandolinje

● Aktivt prosjekt

● Grei dokumentasjon

https://github.com/mbj/mutant

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

HVORDAN KOMME I GANG?

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

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

OPPSUMMERING

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

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

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

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

Takk for din oppmerksomhet!

72

Contact information:

@filipvanlaenen

fvl@computas.com / f.a.vanlaenen@ieee.org

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

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

Recommended