SlideShare ist ein Scribd-Unternehmen logo
1 von 45
Downloaden Sie, um offline zu lesen
Ralf D. Müller @RalfDMueller Johannes Dienst @JohannesDienst
Spock vs Supermutanten
Spezifikationstesten trifft auf Mutationstesten
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
Was ist Spock?
Was ist Spock?
3
Leonard
Brüning
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
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
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
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
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
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
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
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
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
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
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
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst14
Reports
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst15
Reports
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst16
Reports
Product
Owner
Developer
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst17
100%
Zeilenabdeckung?
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst18
100%
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst19
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
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst20
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
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst21
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
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst22
Und nun?
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst23
Fehler gezielt provozieren
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst24
Automatisierung
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst25
Mutationstesten
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst26
Mutationstesten - Funktionsweise
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst27
DEMO HTML
Report
Icons made by Sprang from www.flaticon.com
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 @JohannesDienst28
Default Mutatoren
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 @JohannesDienst29
Default Mutatoren
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 @JohannesDienst30
Default Mutatoren
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 @JohannesDienst31
Default Mutatoren
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 @JohannesDienst32
Default Mutatoren
public Object foo() {
return new Object();
}
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst33
Code Smells finden mit dem Return Values Mutator
public Object foo() {
new Object();
return null;
}
public Object foo() {
return new Object();
}
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst34
Code Smells finden mit dem Return Values Mutator
public Object foo() {
new Object();
return null;
}
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst35
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
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst36
Ä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
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst37
Warum PIT?
Schnell durch
Parallelisierung
Arbeitet auf
Bytecode
Lesbare
Reports
Tooling
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst38
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst39
Mutationstesten – im größeren Team
Icons made by Sprang from www.flaticon.com
Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst40
Mutationstesten – im größeren Team
Icons made by Sprang from www.flaticon.com
41
42
43
Welche zwei Fragen sind noch offen?
Johannes.Dienst@DeutscheBahn.com
@JohannesDienst
Ralf.D.Mueller@DeutscheBahn.com
@RalfDMueller
DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst45
https://jaxenter.de/mutant-testing-pit-java-84437
https://m.heise.de/developer/artikel/Mutationstests-mit-PIT-in-
Java-3888683.html?seite=all

Weitere ähnliche Inhalte

Mehr von Johannes Dienst

Griechische Philosophie für moderne Softwareentwicklung
Griechische Philosophie für moderne SoftwareentwicklungGriechische Philosophie für moderne Softwareentwicklung
Griechische Philosophie für moderne SoftwareentwicklungJohannes Dienst
 
Lessons Learned Using arc42 in a Real DevOps Team
Lessons Learned Using arc42 in a Real DevOps TeamLessons Learned Using arc42 in a Real DevOps Team
Lessons Learned Using arc42 in a Real DevOps TeamJohannes Dienst
 
Lessons Learned: arc42 in einem echten DevOps Team
Lessons Learned: arc42 in einem echten DevOps TeamLessons Learned: arc42 in einem echten DevOps Team
Lessons Learned: arc42 in einem echten DevOps TeamJohannes Dienst
 
Work efficiently with Architecture Decision Records
Work efficiently with Architecture Decision RecordsWork efficiently with Architecture Decision Records
Work efficiently with Architecture Decision RecordsJohannes Dienst
 
The Dev, The Ops, And The Team: What works in a DevOps Team?
The Dev, The Ops, And The Team: What works in a DevOps Team?The Dev, The Ops, And The Team: What works in a DevOps Team?
The Dev, The Ops, And The Team: What works in a DevOps Team?Johannes Dienst
 
Effizient arbeiten mit Architecture Decision Records (ADR)
Effizient arbeiten mit Architecture Decision Records (ADR)Effizient arbeiten mit Architecture Decision Records (ADR)
Effizient arbeiten mit Architecture Decision Records (ADR)Johannes Dienst
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Johannes Dienst
 
Everything as Code: Pipeline, Infrastructure, Configuration, Documentation
Everything as Code: Pipeline, Infrastructure, Configuration, DocumentationEverything as Code: Pipeline, Infrastructure, Configuration, Documentation
Everything as Code: Pipeline, Infrastructure, Configuration, DocumentationJohannes Dienst
 
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)Johannes Dienst
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Johannes Dienst
 
Pride & Prejudice: Teambildung & Motivation im agilen Umfeld
Pride & Prejudice: Teambildung & Motivation im agilen UmfeldPride & Prejudice: Teambildung & Motivation im agilen Umfeld
Pride & Prejudice: Teambildung & Motivation im agilen UmfeldJohannes Dienst
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Johannes Dienst
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Johannes Dienst
 
DevOps im Konzern: Autonomie vs Betriebssicherheit
DevOps im Konzern: Autonomie vs BetriebssicherheitDevOps im Konzern: Autonomie vs Betriebssicherheit
DevOps im Konzern: Autonomie vs BetriebssicherheitJohannes Dienst
 
Und wer testet die Tests? - Mutationstesten mit PIT
Und wer testet die Tests? - Mutationstesten mit PITUnd wer testet die Tests? - Mutationstesten mit PIT
Und wer testet die Tests? - Mutationstesten mit PITJohannes Dienst
 
Type Script 3.x - Was war. Was kommt!
Type Script 3.x - Was war. Was kommt!Type Script 3.x - Was war. Was kommt!
Type Script 3.x - Was war. Was kommt!Johannes Dienst
 
Ist das Softwarearchitektur oder kann das weg?
Ist das Softwarearchitektur oder kann das weg?Ist das Softwarearchitektur oder kann das weg?
Ist das Softwarearchitektur oder kann das weg?Johannes Dienst
 
Clean Code ist doch einfach... Qualität ist schwierig!
Clean Code ist doch einfach... Qualität ist schwierig!Clean Code ist doch einfach... Qualität ist schwierig!
Clean Code ist doch einfach... Qualität ist schwierig!Johannes Dienst
 

Mehr von Johannes Dienst (18)

Griechische Philosophie für moderne Softwareentwicklung
Griechische Philosophie für moderne SoftwareentwicklungGriechische Philosophie für moderne Softwareentwicklung
Griechische Philosophie für moderne Softwareentwicklung
 
Lessons Learned Using arc42 in a Real DevOps Team
Lessons Learned Using arc42 in a Real DevOps TeamLessons Learned Using arc42 in a Real DevOps Team
Lessons Learned Using arc42 in a Real DevOps Team
 
Lessons Learned: arc42 in einem echten DevOps Team
Lessons Learned: arc42 in einem echten DevOps TeamLessons Learned: arc42 in einem echten DevOps Team
Lessons Learned: arc42 in einem echten DevOps Team
 
Work efficiently with Architecture Decision Records
Work efficiently with Architecture Decision RecordsWork efficiently with Architecture Decision Records
Work efficiently with Architecture Decision Records
 
The Dev, The Ops, And The Team: What works in a DevOps Team?
The Dev, The Ops, And The Team: What works in a DevOps Team?The Dev, The Ops, And The Team: What works in a DevOps Team?
The Dev, The Ops, And The Team: What works in a DevOps Team?
 
Effizient arbeiten mit Architecture Decision Records (ADR)
Effizient arbeiten mit Architecture Decision Records (ADR)Effizient arbeiten mit Architecture Decision Records (ADR)
Effizient arbeiten mit Architecture Decision Records (ADR)
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
 
Everything as Code: Pipeline, Infrastructure, Configuration, Documentation
Everything as Code: Pipeline, Infrastructure, Configuration, DocumentationEverything as Code: Pipeline, Infrastructure, Configuration, Documentation
Everything as Code: Pipeline, Infrastructure, Configuration, Documentation
 
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)
DevOps im Konzern - Autonomie vs Betriebssicherheit (Continuous Lifecycle)
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
 
Pride & Prejudice: Teambildung & Motivation im agilen Umfeld
Pride & Prejudice: Teambildung & Motivation im agilen UmfeldPride & Prejudice: Teambildung & Motivation im agilen Umfeld
Pride & Prejudice: Teambildung & Motivation im agilen Umfeld
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
 
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
Leichtgewichtige Softwarearchitektur mit Architecture Decision Records und Qu...
 
DevOps im Konzern: Autonomie vs Betriebssicherheit
DevOps im Konzern: Autonomie vs BetriebssicherheitDevOps im Konzern: Autonomie vs Betriebssicherheit
DevOps im Konzern: Autonomie vs Betriebssicherheit
 
Und wer testet die Tests? - Mutationstesten mit PIT
Und wer testet die Tests? - Mutationstesten mit PITUnd wer testet die Tests? - Mutationstesten mit PIT
Und wer testet die Tests? - Mutationstesten mit PIT
 
Type Script 3.x - Was war. Was kommt!
Type Script 3.x - Was war. Was kommt!Type Script 3.x - Was war. Was kommt!
Type Script 3.x - Was war. Was kommt!
 
Ist das Softwarearchitektur oder kann das weg?
Ist das Softwarearchitektur oder kann das weg?Ist das Softwarearchitektur oder kann das weg?
Ist das Softwarearchitektur oder kann das weg?
 
Clean Code ist doch einfach... Qualität ist schwierig!
Clean Code ist doch einfach... Qualität ist schwierig!Clean Code ist doch einfach... Qualität ist schwierig!
Clean Code ist doch einfach... Qualität ist schwierig!
 

Spock vs Supermutanten: Spezifikationstesten trifft Mutationstesten

  • 1. Ralf D. Müller @RalfDMueller Johannes Dienst @JohannesDienst Spock vs Supermutanten Spezifikationstesten trifft auf Mutationstesten
  • 2. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst Was ist Spock?
  • 3. Was ist Spock? 3 Leonard Brüning Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst
  • 4. 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
  • 5. 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
  • 6. 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
  • 7. 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
  • 8. 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
  • 9. 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
  • 10. 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
  • 11. 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
  • 12. 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
  • 13. 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
  • 14. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst14 Reports
  • 15. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst15 Reports
  • 16. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst16 Reports Product Owner Developer
  • 17. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst17 100% Zeilenabdeckung?
  • 18. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst18 100% Icons made by Sprang from www.flaticon.com
  • 19. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst19 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
  • 20. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst20 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
  • 21. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst21 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
  • 22. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst22 Und nun? Icons made by Sprang from www.flaticon.com
  • 23. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst23 Fehler gezielt provozieren Icons made by Sprang from www.flaticon.com
  • 24. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst24 Automatisierung Icons made by Sprang from www.flaticon.com
  • 25. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst25 Mutationstesten Icons made by Sprang from www.flaticon.com
  • 26. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst26 Mutationstesten - Funktionsweise Icons made by Sprang from www.flaticon.com
  • 27. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst27 DEMO HTML Report Icons made by Sprang from www.flaticon.com
  • 28. 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 @JohannesDienst28 Default Mutatoren
  • 29. 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 @JohannesDienst29 Default Mutatoren
  • 30. 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 @JohannesDienst30 Default Mutatoren
  • 31. 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 @JohannesDienst31 Default Mutatoren
  • 32. 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 @JohannesDienst32 Default Mutatoren
  • 33. public Object foo() { return new Object(); } Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst33 Code Smells finden mit dem Return Values Mutator public Object foo() { new Object(); return null; }
  • 34. public Object foo() { return new Object(); } Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst34 Code Smells finden mit dem Return Values Mutator public Object foo() { new Object(); return null; }
  • 35. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst35 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
  • 36. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst36 Ä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
  • 37. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst37 Warum PIT? Schnell durch Parallelisierung Arbeitet auf Bytecode Lesbare Reports Tooling
  • 38. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst38
  • 39. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst39 Mutationstesten – im größeren Team Icons made by Sprang from www.flaticon.com
  • 40. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst40 Mutationstesten – im größeren Team Icons made by Sprang from www.flaticon.com
  • 41. 41
  • 42. 42
  • 43. 43
  • 44. Welche zwei Fragen sind noch offen? Johannes.Dienst@DeutscheBahn.com @JohannesDienst Ralf.D.Mueller@DeutscheBahn.com @RalfDMueller
  • 45. DB Systel. Digital bewegen. Gemeinsam. Ralf D. Müller @RalfDMueller und Johannes Dienst @JohannesDienst45 https://jaxenter.de/mutant-testing-pit-java-84437 https://m.heise.de/developer/artikel/Mutationstests-mit-PIT-in- Java-3888683.html?seite=all