39
© 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch lesen magst! 6. November 2019 XP Days Germany 2019 Claudia Fuhrmann André Kappes

Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2018 andrena objects ag

Experts in agile software engineering

andrena objects ag

Schreib‘ die Tests, die du auch lesen magst!

6. November 2019

XP Days Germany 2019

Claudia Fuhrmann

André Kappes

Page 2: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Wer von Euch hat…

… schon einmal an einem roten Test gesessen und nicht

verstanden, was er eigentlich bewirken soll?

… diesen Test selbst geschrieben?

2

Page 3: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 3

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Page 4: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Das Projekt

Page 5: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Online - Obstversand

5

Warenkorb

Birne

Apfel

Banane Orange

Ananas Kiwi

Kasse

Vorkasse

PayPal

Rechnung

Kreditkarte

Lastschrift

Preisberechnung

Preisreduzierungen,

z.B. ab der X-ten

Birne kostet jede

weitere nur noch Y €

Page 6: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 6

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Page 7: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Regeln aus der Typografie

7

• Lange Zeilen bzw. Umbrüche vermeiden

• Durch Absätze strukturieren

• AAA-Pattern zur Orientierung: Gliederung des Tests in Abschnitten nach Arrange – Act – Assert

Experts in agile software engineering

Page 8: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Strukturierung mit dem AAA-Pattern

@Test

void testAdd() {

PreisRepository preisRepository = new PreisRepository();

preisRepository.save(ObstTyp.BIRNE,

PreisStrategyFactory.createNormalPreisStrategy(Money.of(0.70)));

Warenkorb warenkorb = new Warenkorb(preisRepository);

warenkorb.add(5, ObstTyp.BIRNE);

warenkorb.add(3, ObstTyp.BIRNE);

List<Posten> posten = warenkorb.getPosten();

assertEquals(ObstTyp.BIRNE, posten.get(0).getTyp());

assertEquals(8, posten.get(0).getAnzahl());

assertEquals(Money.of(5.60), posten.get(0).getPreis());

}

8

Page 9: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Strukturierung mit dem AAA-Pattern

@Test

void testAdd() {

PreisRepository preisRepository = new PreisRepository();

preisRepository.save(ObstTyp.BIRNE,

PreisStrategyFactory.createNormalPreisStrategy(Money.of(0.70)));

Warenkorb warenkorb = new Warenkorb(preisRepository);

warenkorb.add(5, ObstTyp.BIRNE);

warenkorb.add(3, ObstTyp.BIRNE);

List<Posten> posten = warenkorb.getPosten();

assertEquals(ObstTyp.BIRNE, posten.get(0).getTyp());

assertEquals(8, posten.get(0).getAnzahl());

assertEquals(Money.of(5.60), posten.get(0).getPreis());

}

9

Arrange

Act

Assert

Page 10: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 10

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Page 11: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Wie soll sie denn heißen? Sprechende Namen finden

*) Variable, Testmethode

*

Experts in agile software engineering

Page 12: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Sprechende Namen finden

class BestellServiceTest {

private KundenRepository repositoryMock = mock(KundenRepository.class);

private BestellService service = new BestellService(repositoryMock);

@Test

void berechnePreis() {

PreisRepository repository = new PreisRepository();

repository.save(BIRNE, reduzierterPreisAb(5, of(0.70), of(0.50)));

Warenkorb input = new Warenkorb(repository);

input.add(5, BIRNE);

BestellUebersicht bU = service.getBestellUebersicht(input);

assertEquals(Money.of(3.30), bU.getGesamtpreis());

}

}

12

Page 13: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Gute Namen

• Zweck der Variablen / des Felds in diesem Testfall erklären

• Generische Namen vermeiden – spezifische Namen bevorzugen

• Lesbar / aussprechbar

• Je kleiner der Scope, desto kürzer der Name

• Unterscheidbare Namen verwenden

13 Experts in agile software engineering

Page 14: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Magic Values

@Test

void berechnePreis() {

PreisRepository preisRepository = new PreisRepository();

preisRepository.save(BIRNE, reduzierterPreisAb(5, of(0.70), of(0.50)));

Warenkorb mit5Birnen = new Warenkorb(preisRepository);

mit5Birnen.add(5, BIRNE);

BestellUebersicht uebersicht = bestellService.getBestellUebersicht(mit5Birnen);

assertEquals(Money.of(3.30), uebersicht.getGesamtpreis());

}

15

Warum 3.30?

Page 15: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Magic Values

@Test

void berechnePreis() {

PreisRepository preisRepository = new PreisRepository();

preisRepository.save(BIRNE, reduzierterPreisAb(5, of(0.70), of(0.50)));

Warenkorb mit5Birnen = new Warenkorb(preisRepository);

mit5Birnen.add(5, BIRNE);

BestellUebersicht uebersicht = bestellService.getBestellUebersicht(mit5Birnen);

assertEquals(PREIS_FUER_VIER_BIRNEN.plus(REDUZIERTER_PREIS_FUER_FUENFTE_BIRNE),

uebersicht.getGesamtpreis());

}

16

Erklärende Konstanten

Page 16: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Testmethoden benennen

Namenskonvention von Roy Osherove:

Function/Feature – Input/State – Outcome/Behaviour

17 Experts in agile software engineering

@Test void berechnePreis_reduktionAb5Birnen_wirdBeachtet() { ... }

@Test void berechnePreis () { ... }

Page 17: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Empfehlungen

• Erklärende Namen für lokale Variablen und Felder wählen

• Testmethode aussagekräftig benennen

• Magic Values vermeiden

18

Page 18: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 19

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Page 19: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Prägnanz

private Posten EINE_ANANAS = Posten.of(1, ANANAS, Money.of(3.00));

private Posten EINE_BANANE = Posten.of(1, BANANE, Money.of(2.00));

private Posten EIN_APFEL = Posten.of(1, APFEL, Money.of(1.50));

private Posten EINE_BIRNE = Posten.of(1, BIRNE, Money.of(1.00));

private Posten EINE_KIWI = Posten.of(1, KIWI, Money.of(3.50));

private Posten EINE_ORANGE = Posten.of(1, ORANGE, Money.of(2.50));

private PreisRepository preisRepository;

private KundenRepository kundenRepository;

@BeforeEach

void setUp() {

preisRepository = new PreisRepository();

PreisRepositoryInitializer.create(preisRepository).init();

kundenRepository = new KundenRepository();

}

20

@Test

void testWarenkorb() {

Warenkorb warenkorb = new Warenkorb(preisRepository);

warenkorb.add(1, ANANAS);

warenkorb.add(1, BANANE);

warenkorb.add(1, APFEL);

warenkorb.add(1, BIRNE);

warenkorb.add(1, KIWI);

warenkorb.add(1, ORANGE);

UUID kundenId = warenkorb.getKundenId();

assertThat(kundenId).isNotNull();

List<Posten> posten = warenkorb.getPosten();

assertThat(posten).contains(EINE_ANANAS);

assertThat(posten).contains(EINE_BANANE);

assertThat(posten).contains(EIN_APFEL);

assertThat(posten).contains(EINE_BIRNE);

assertThat(posten).contains(EINE_KIWI);

assertThat(posten).contains(EINE_ORANGE);

}

KundenId setzen

Posten im Warenkorb

Zu lang und unübersichtlich!

Page 20: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Fragen, die ich mir stellen sollte, wenn der Test zu lang ist:

• Kann man den Test aufteilen, weil nicht alles in diesen Test gehört?

• Gehören die einzelnen Asserts in eine andere Testklasse?

• Hat die getestete Klasse zu viele Verantwortlichkeiten?

21

Page 21: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Prägnanz

22

@Test void kundenIdIstNichtNull() { Warenkorb warenkorb = new Warenkorb(preisRepository);

UUID kundenId = warenkorb.getKundenId();

assertThat(kundenId).isNotNull(); } @Test void getPosten() { Warenkorb warenkorb = WarenkorbBuilder.get() .addAnanas(1) .addBananen(1).create();

List<Posten> posten = warenkorb.getPosten();

assertThat(posten).containsExactlyInAnyOrder(EINE_ANANAS, EINE_BANANE); }

Kurze Tests

Wenige Zusicherungen

Page 22: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Empfehlungen

Tests sollten:

• kurz sein

• wenige Zusicherungen haben, am besten nur eine

• in den dazugehörigen Testklassen sein

Wenn dein Test nicht mehr auf deinen Bildschirm passt, ist er definitiv zu lang!

23

Page 23: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Sprechende Zusicherungen und Fehlermeldungen

@Test

void testZahlungsService() {

BestellUebersicht ueberLimit = mock(BestellUebersicht.class);

when(ueberLimit.getGesamtpreis()).thenReturn(UEBER_LIMIT_FUER_RECHNUNG);

ZahlungsService zahlungsService = new ZahlungsService(new KundenRepository());

List<ZahlungsArt> angeboteneZahlungsArten = zahlungsService.getZahlungsarten(ueberLimit);

assertTrue(!angeboteneZahlungsArten.contains(ZahlungsArt.RECHNUNG));

}

24

Negation Keine Informationen über den Grund eines Fehlschlags

Page 24: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Sprechende Zusicherungen und Fehlermeldungen

@Test

void testZahlungsService() {

BestellUebersicht ueberLimit = mock(BestellUebersicht.class);

when(ueberLimit.getGesamtpreis()).thenReturn(UEBER_LIMIT_FUER_RECHNUNG);

ZahlungsService zahlungsService = new ZahlungsService(new KundenRepository());

List<ZahlungsArt> angeboteneZahlungsArten = zahlungsService.getZahlungsarten(ueberLimit);

assertTrue(!angeboteneZahlungsArten.contains(ZahlungsArt.RECHNUNG),"Zahlart 'Rechnung‘ nicht enthalten!");

}

25

Aussagekräftiger Kommentarstring

Page 25: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Sprechende Zusicherungen und Fehlermeldungen

@Test

void testZahlungsService() {

BestellUebersicht ueberLimit = mock(BestellUebersicht.class);

when(ueberLimit.getGesamtpreis()).thenReturn(UEBER_LIMIT_FUER_RECHNUNG);

ZahlungsService zahlungsService = new ZahlungsService(new KundenRepository());

List<ZahlungsArt> angeboteneZahlungsArten = zahlungsService.getZahlungsarten(ueberLimit);

assertThat(angeboteneZahlungsArten).doesNotContain(ZahlungsArt.RECHNUNG);

}

26

Assertj Matcher

Page 26: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Empfehlungen

• Zusicherungen möglichst präzise formulieren

• Auf sprechende Fehlermeldung im Testfehlschlags-Fall achten

27

Page 27: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 28

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Page 28: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Hin- und Herspringen

public class BestellUebersichtTest extends WarenkorbTest { private Posten EINE_BANANE = Posten.of(1, BANANE, Money.of(2.00)); private Posten EINE_ANANAS = Posten.of(1, ANANAS, Money.of(3.00)); private PreisRepository preisRepository = new PreisRepository(); private KundenRepository kundenRepository; private BestellService underTest; @BeforeEach void setUp() { PreisRepositoryInitializer.create(preisRepository).init(); underTest = new BestellService(kundenRepository); }

29

Wie sehen die Preise aus?

Warum? Was gibt es dort?

Page 29: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Hin- und Herspringen

@Test void getBestellUebersicht_eineAnanasUndEineBanane_BestelluebersichtOk() { Warenkorb warenkorb = createWarenkorbWithAnanasUndBanane(preisRepository);

BestellUebersicht bestellUebersicht = underTest.getBestellUebersicht(warenkorb);

assertBestellUebersicht(bestellUebersicht, warenkorb.getKundenId(), Money.of(5.00), EINE_ANANAS, EINE_BANANE); } private void assertBestellUebersicht(BestellUebersicht bestellUebersicht, UUID kundenId, Money preis, Posten... posten) { assertThat(bestellUebersicht.getGesamtpreis()).isEqualTo(preis); assertThat(bestellUebersicht.getPosten()).containsExactlyInAnyOrder(posten); assertThat(bestellUebersicht.getKundenId()).isEqualTo(kundenId); }

30

Wo finde ich diese Methode?

Was testet dieses Assert?

Page 30: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Hin- und Herspringen

public class BestellServiceTest {

private Money PREIS_EINE_ANANAS = Money.of(3.00);

private Money PREIS_EINE_BANANE = Money.of(2.00);

private Posten EINE_ANANAS = Posten.of(1, ANANAS, PREIS_EINE_ANANAS);

private Posten EINE_BANANE = Posten.of(1, BANANE, PREIS_EINE_BANANE);

private KundenRepository kundenRepository;

private BestellService underTest;

@BeforeEach

void setUp() {

kundenRepository = new KundenRepository();

underTest = new BestellService(kundenRepository);

}

31

Keine magische Preiserstellung

Page 31: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Hin- und Herspringen

@Test

void getBestellUebersicht_eineAnanasUndEineBanane_BestelluebersichtOk() {

Warenkorb warenkorb = WarenkorbBuilder.warenkorb().withKundenId(KUNDEN_ID)

.addAnanas(1, PREIS_EINE_ANANAS)

.addBananen(1, PREIS_EINE_BANANE).create();

BestellUebersicht bestellUebersicht = underTest.getBestellUebersicht(warenkorb);

assertThat(bestellUebersicht)

.hasGesamtpreis(PREIS_EINE_ANANAS.plus(PREIS_EINE_BANANE))

.hasPosten(EINE_ANANAS, EINE_BANANE)

.hasKundenId(KUNDEN_ID);

}

32

Builder, der den Warenkorb samt Preise erstellt

Custom matcher

Page 32: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Empfehlungen und Lösungsansätze

• Relevantes sichtbar machen, Irrelevantes verbergen

• Builder Pattern

• Custom Matchers

33

Page 33: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Noise stört die Lesbarkeit

@Test

void testAdd() {

PreisRepository preisRepository = new PreisRepository();

preisRepository.save(ObstTyp.BIRNE,

PreisStrategyFactory.createNormalPreisStrategy(Money.of(0.70)));

Warenkorb warenkorb = new Warenkorb(preisRepository);

warenkorb.add(5, ObstTyp.BIRNE);

warenkorb.add(3, ObstTyp.BIRNE);

List<Posten> posten = warenkorb.getPosten();

assertEquals(ObstTyp.BIRNE, posten.get(0).getTyp());

assertEquals(8, posten.get(0).getAnzahl());

assertEquals(Money.of(5.60), posten.get(0).getPreis());

}

34

Page 34: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Weniger Noise durch Syntactic Sugar

@Test

void testAdd() {

PreisRepository repository = new PreisRepository();

repository.save(BIRNE, normalPreis(0.70));

Warenkorb warenkorb = new Warenkorb(repository);

warenkorb.add(5, BIRNE);

warenkorb.add(3, BIRNE);

Posten soleItem = warenkorb.getPosten().get(0);

assertEquals(BIRNE, soleItem.getTyp());

assertEquals(8, soleItem.getAnzahl());

assertEquals(Money.of(5.60), soleItem.getPreis());

}

35

Static imports verwenden

Erklärende Variablen einführen

private PreisStrategy normalPreis(double value) { return PreisStrategyFactory.createNormalPreisStrategy(of(value)); }

Syntactic sugar-Methoden extrahieren

Page 35: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering 36

Zusammenfassung

Page 36: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Code-Typografie

Experts in agile software engineering 37

Namensgebung

Übersichtlichkeit Prägnanz

Lesbare Tests

Kümmere Dich um Eure Tests!

Nimm Dein Team mit!

Page 37: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Referenzen

Bücher

• Roy Osherove, The Art of Unit Testing (Manning, 2013)

• Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code (Addison Wesley, 2007) http://xunitpatterns.com/

Blogs

• Petri Kainulainen, Writing Clean Tests https://www.petrikainulainen.net/writing-clean-tests/

• Thomas Countz, Essential & Relevant: A Unit Test Balancing Act https://8thlight.com/blog/thomas-countz/2019/02/19/essential-and-relevant-unit-tests.html

38

Page 38: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Vielen Dank!

Experts in agile software engineering

Page 39: Schreib' die Tests, die du auch lesen magst! · 2019-12-20 · © 2018 andrena objects ag Experts in agile software engineering andrena objects ag Schreib‘ die Tests, die du auch

© 2019 andrena objects ag

Experts in agile software engineering

Euer Feedback

Schreib‘ die Tests, die du auch lesen magst!