Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spock vs Supermutanten: Spezifikationstesten tr...

Spock vs Supermutanten: Spezifikationstesten trifft Mutationstesten

http://cyberland.ijug.eu/sessions/session-9.html

Johannes Dienst, Ralf Müller

Das Spock-Testframework verwendet das ausdrucksstarke Groovy, um BDD als Testansatz zu realisieren. Neben einer klaren Teststruktur punktet es außerdem mit lesbaren Reports, die dank einer Template-Engine auch in AsciiDoc generiert werden können. Dazu kommt die problemlose Integrierbarkeit mit allen wichtigen Testbibliotheken.

Kann man das noch verbessern? Ja! Wir treten den Beweis an und kombinieren Spock mit Mutationstests. Bereits 1971 vorgeschlagen, gewinnt es heute mit leistungsfähigen Multicore-Prozessoren immer mehr an Bedeutung. Denn eine Testabdeckung von über 80 Prozent beweist noch nicht, dass die Testsuite in der Lage ist, Fehler zuverlässig zu erkennen. Also lassen wir die Mutanten los und bringen die Fehler rein. Spock wird sie hoffentlich mit seiner kühlen Logik finden.

Der Vortrag zeigt, wie sich Spock mit Mutationstesten zu einem unschlagbaren Duo kombinieren lässt.

Ralf D. Müller

March 17, 2020
Tweet

More Decks by Ralf D. Müller

Other Decks in Programming

Transcript

  1. Was ist Spock? 4 private Fibonacci fib; @Before public void

    setup() { fib = new Fibonacci(); } @Test public void seedValue0() { assertEquals(0, fib.calc(0)); } @Test public void seedValue1() { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  2. Was ist Spock? 5 private Fibonacci fib; @Before public void

    setup() { fib = new Fibonacci(); } @Test public void seedValue0() { assertEquals(0, fib.calc(0)); } @Test public void seedValue1() { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  3. Was ist Spock? 6 private Fibonacci fib; @Before public void

    setup() { fib = new Fibonacci(); } @Test public void seedValue0() { assertEquals(0, fib.calc(0)); } @Test public void seedValue1() { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  4. Was ist Spock? 7 Fibonacci fib; @Before void setup() {

    fib = new Fibonacci(); } void seedValue0() { assertEquals(0, fib.calc(0)); } void seedValue1() { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  5. Was ist Spock? 8 Fibonacci fib; @Before void setup() {

    fib = new Fibonacci(); } void "test the fibonacci generator with input 0"() { assertEquals(0, fib.calc(0)); } void "test the fibonacci generator with input 1" { assertEquals(1, fib.calc(1)); } // … Developer Product Owner Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  6. Was ist Spock? 9 Fibonacci fib; @Before void setup() {

    fib = new Fibonacci(); } void "test the fibonacci generator with input 0"() { given: Fibonacci fib = new Fibonacci() when: def result = fib.calc(i) then: assertEquals(0, fib.calc(0)); } void "test the fibonacci generator with input 1" { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  7. Was ist Spock? 10 void "test the fibonacci generator with

    input 0"() { given: Fibonacci fib = new Fibonacci() when: def result = fib.calc(i) then: assertEquals(0, fib.calc(0)); } void "test the fibonacci generator with input 1" { assertEquals(1, fib.calc(1)); } // … Developer Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  8. Was ist Spock? 11 void "test the fibonacci generator with

    input 0"() { given: "an instance of the fibonacci generator" Fibonacci fib = new Fibonacci() when: "the fib sequence for 0 is calculated" def result = fib.calc(i) then: "the expected number is returned" assertEquals(0, fib.calc(0)); } void "test the fibonacci generator with input 1" { assertEquals(1, fib.calc(1)); } // … Developer Product Owner Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  9. Was ist Spock? 12 void "test the fibonacci generator with

    input 0"() { given: "an instance of the fibonacci generator" Fibonacci fib = new Fibonacci() when: "the fib sequence for 0 is calculated" def result = fib.calc(i) then: "the expected number is returned" result == expected } void "test the fibonacci generator with input 1" { assertEquals(1, fib.calc(1)); } // … Developer Product Owner Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  10. Was ist Spock? 13 void "test the fibonacci generator with

    input 0"() { given: "an instance of the fibonacci generator" Fibonacci fib = new Fibonacci() when: "the fib sequence for a given input #i is calculated" def result = fib.calc(i) then: "the expected number #expected is returned" result == expected where: i || expected 0 || 0 2 || 1 11 || 89 } Developer Product Owner Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  11. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und

    Johannes Dienst @JohannesDienst 16 Reports Product Owner Developer
  12. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 19 Finde

    den Fehler? public List<Integer> sort(List<Integer> coll) { List<Integer> list = new ArrayList<>(coll); Collections.sort(list); log(list); return Collections.unmodifiableList(list); } public void log(List<Integer> list) { System.out.println( list.stream().map(Object::toString) .collect(Collectors.joining(", "))); } Icons made by Sprang from www.flaticon.com
  13. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 20 Finde

    den Fehler? def "test Sort"() { given: "an instance of Sort" def Sort = new Sort() when: "the given list #list is sorted" def result = Sort.sort(list) then: "the result is as #expected" result == expected where: "" list || expected [] || [] [5] || [5] [2,1,3,8] || [1,2,3,8] } Icons made by Sprang from www.flaticon.com
  14. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 21 Finde

    den Fehler? public List<Integer> sort(List<Integer> coll) { List<Integer> list = new ArrayList<>(coll); Collections.sort(list); log(list); return Collections.unmodifiableList(list); } public void log(List<Integer> list) { System.out.println( list.stream().map(Object::toString) .collect(Collectors.joining(", "))); } Icons made by Sprang from www.flaticon.com
  15. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 22 Und

    nun? Icons made by Sprang from www.flaticon.com
  16. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 23 Fehler

    gezielt provozieren Icons made by Sprang from www.flaticon.com
  17. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 26 Mutationstesten

    - Funktionsweise Icons made by Sprang from www.flaticon.com
  18. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 27 DEMO

    HTML Report Icons made by Sprang from www.flaticon.com
  19. Increments Mutator i++ wird zu i-- Math Mutator + wird

    zu - * wird zu / Negate Conditionals Mutator == wird zu != <= wird zu > Conditionals Boundary Mutator < wird zu <= <= wird zu < Invert Negs Mutator -i wird zu i Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 28 Default Mutatoren
  20. Increments Mutator i++ wird zu i-- Math Mutator + wird

    zu - * wird zu / Negate Conditionals Mutator == wird zu != <= wird zu > Conditionals Boundary Mutator < wird zu <= <= wird zu < Invert Negs Mutator -i wird zu i Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 29 Default Mutatoren
  21. Increments Mutator i++ wird zu i-- Math Mutator + wird

    zu - * wird zu / Negate Conditionals Mutator == wird zu != <= wird zu > Conditionals Boundary Mutator < wird zu <= <= wird zu < Invert Negs Mutator -i wird zu i Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 30 Default Mutatoren
  22. Increments Mutator i++ wird zu i-- Math Mutator + wird

    zu - * wird zu / Negate Conditionals Mutator == wird zu != <= wird zu > Conditionals Boundary Mutator < wird zu <= <= wird zu < Invert Negs Mutator -i wird zu i Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 31 Default Mutatoren
  23. Increments Mutator i++ wird zu i-- Math Mutator + wird

    zu - * wird zu / Negate Conditionals Mutator == wird zu != <= wird zu > Conditionals Boundary Mutator < wird zu <= <= wird zu < Invert Negs Mutator -i wird zu i Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 32 Default Mutatoren
  24. public Object foo() { return new Object(); } Ralf D.

    Müller @RalfDMueller und Johannes Dienst @JohannesDienst 33 Code Smells finden mit dem Return Values Mutator public Object foo() { new Object(); return null; }
  25. public Object foo() { return new Object(); } Ralf D.

    Müller @RalfDMueller und Johannes Dienst @JohannesDienst 34 Code Smells finden mit dem Return Values Mutator public Object foo() { new Object(); return null; }
  26. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und

    Johannes Dienst @JohannesDienst 35 Dead Code finden mit dem Void Method Call Mutator public List<Integer> sort(List<Integer> coll) { List<Integer> list = new ArrayList<>(coll); Collections.sort(list); log(list); return Collections.unmodifiableList(list); } public void log(List<Integer> list) { System.out.println( list.stream().map(Object::toString) .collect(Collectors.joining(", "))); } Icons made by Sprang from www.flaticon.com
  27. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 36 Äquivalente

    Mutationen public int calc(int i) { if (i == 0) { return 0; } if (i <= 2) { return 1; } return calc(i-1) + calc(i-2); } def "test fibonacci generator"() { given: "fibonacci generator" Fibonacci fib = new Fibonacci() when: "calc sequence for input #i" def result = fib.calc(i) then: "expected number is returned" result == expected where: i || expected 0 || 0 2 || 1 11 || 89 } i < 2 Icons made by Sprang from www.flaticon.com
  28. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 37 Warum

    PIT? Schnell durch Parallelisierung Arbeitet auf Bytecode Lesbare Reports Tooling
  29. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 39 Mutationstesten

    – im größeren Team Icons made by Sprang from www.flaticon.com
  30. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst 40 Mutationstesten

    – im größeren Team Icons made by Sprang from www.flaticon.com
  31. 41

  32. 42

  33. 43

  34. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und

    Johannes Dienst @JohannesDienst 45 https://jaxenter.de/mutant-testing-pit-java-84437 https://m.heise.de/developer/artikel/Mutationstests-mit-PIT-in- Java-3888683.html?seite=all