width: 900 height: 900 maxScale: 1.5
SE-Tutorium 4 | Mittwoch 16 - 18 Uhr:
anchored to [[191.00_anchor]]
Lernziele:
- Gründe / Motivation für Tests wiederholen
- Was macht gute Tests aus?
- Wie erkennen wir schlechte / suboptimale tests?
- wie schreiben wir gute Tests?
| Orga | Aktuelle Abgaben
- HW8 (weiterhin machbar!)-> bis zum 28.01
- HW10 verfügbar! –> Gruppen erstellen! Abgabe am 28.01
- Erstellt die Gruppen und Teams!
- Helpdesk jeden Freitag 16-18 Uhr auf dem Sand!
- Sorry, dass ich HW7 noch nicht korrigierte ( stress )
| Orga | Fragen zu Abgaben / Vorlesung?
Aufgabe | Vorbereitung Tutorium
[!Task] Im REPO (ex11-tut4)
- Repository clonen!
- Projekt im Ordner countClumps öffnen
sbt compile
ausführen –> lädt Dependencies herunter ( brauch etwas)- fertig
note: give them around 5 min ?
Frage: Automated Testing -> Warum?
note: give them something of 3 minutes to think about then talk about possible reasons / aspects to consider here.
Automated Testing | Gründe
- (maintenance) Änderung einer Implementation –> Testen, ob Contract erhalten bleibt ( sonst Fehler!)
- (confidence) Abdecken von Fehlern
- (development) einmal an spezielle Nits denken, danach automatisch
- (robustness) Probleme nicht wieder einführen!
- (documentation) Tests zeigen, wie Implementation funktionieren soll
- (reviewing) –> manuelles Testen von reviewer fällt weg!
Automated Testing | Best Practices
- Tests können verschieden geschrieben werden
- meist: Qualität -> Quantität!
- zu viele Tests können Verständnis | Richtigkeit verwischen
- daher Best-Practices nach denen man sich orientieren kann!
- finden sich auch im Online-Skript ( und Repo!)
Automated Testing | Best Practices
- Tests should be fast
- Tests should be cohesive, independent, and isolated
- Tests should have a reason to exist
- Tests should be repeatable and not flaky
- Tests should have strong assertions
note: go through those practices and discuss them with students
Automated Testing | Best Practices
- Tests should break in case the behaviour changes
- Tests should have a single and clear reason to fail
- Tests should be easy to write
- Tests should be easy to read
- Tests should be easy to change and evolve
Automated Testing | Probleme (Smells)
- Excessive duplication
- Unclear assertions
- Bad handling of complex or external resources
- Fixtures that are too general
- Sensitive assertions
note: will likely explain those myself
excessive duplication: if we have tests that double in their testing range or even their expression then why should we contain those? its added redundancy, time testing and it wont yield any information!
unclear assertions: Maybe we’ve written a test that tests something, well but if it fails we may not know what failed or why it did ( reasoning about its assertion basically) –> what does it mean?
bad handling of some complex / external resources: -> external resources should not be tested –> we are only using this implementation, why test someone elses library / code? –> we cannot ensure that it will work well
fixtures that are too general –> will talk about fixtures in unit testing basically those are creating an environment we will test / make our assumptions in –> if its too general ( testing nothing special), we may not be able to narrow down the error ( if we allow numbers from 0 to 100) but the error happened at 70 –> how should we know about that ?
sensitive assertions -> well they should be sensitive but only for the thing we want to test! –> once again not too general!
Automated Testing | Achtung!
- “Testing can only show the presence of bugs, not their absence” (Dijkstra)
- -> nur weil Tests keine Fehler zeigen, haben wir keinen perfekten Code
- –> Hohe Test-Coverage also keine gute Metrik für Fehler!
- ( wie jede Metrik, kann sie abused werden)
Typen von Tests
Wir möchten Tests in verschiedene Kategorien unterteilen, welche? -> (wir betrachten 4 große)
note: give them introduction to new topic of types/classes of test.
Typen von Tests
![[Pasted image 20240117011333.png]]
note: We will not really be focusing on the latter two ( Style of Specification and Software Attributes) but mostly on Granularity and Code Knowledge!
Unit Tests | kleine Teile Testen
- behandelt testen von Granularen Modulen
- dabei kann der Scope verschieden sein!
- Library / Paket
- große Klasse
- ganzes Modul
- einzelne Funktionen
- …
- benötigt dafür:
- SUT - System under Test –> das zu testende
- Fixture –> “Scope”, den wir zum testen konstruieren ( environment to test in)
Unit Tests | Aufbau
![[Pasted image 20240117013643.png]]
note: wir haben diverse Punkte, die wir durchlaufen müssen, wenn wir Unit-Tests nutzen möchten ||
1 Setup –> Zustand herstellen, den wir zum testen brauch. –> Fixture aufbauen
- kann etwa spezielles Objekt sein, was wir passend initialisieren müssen
2 Interact –> mit dem SUT “interagieren” –> Methoden, Funktionen etc
3 Assert –> Die Ergebnisse von Interact gegen die erwartetenden Werte testen! ( Also etwa )
- hier können bei falschen Asserts schon Fehler auftreten und uns alamieren!
4 Teardown –> die “Fixture” abbauen | Environment zum testen entfernen
Die werden wir größtenteils nutzen hier!
Testing ist auch SE |
- Tests zum Validieren der Funktionalität des getesteten Codes
- ! Wenn Implementation geändert wird, failen Tests auch !
- -> am besten Tests einfach schreiben können ( sonst zu viele Hürden / unlukrativ )
- Drei Methoden wurden dafür kennen gelernt Welche?
Testing ist auch SE |
- Creation Methods –> Helfen uns schnell “Setup” abarbeiten zu können ( bauen Datenstrukturen / Objekte –> Fixture)
- Encapsulation Methods –> Vereinfachen der Interaktion mit SUT ( i.e. komplexes Setup zum Aufrufen / Interaktion mit Sut notwendig)
- Assertion Methods –> Gemäß gegebener Vergleichsparameter testen ( Vergleiche erwarteten Output mit tatsächlichem)
Weitere “Granularity-Tests”
- Integration Tests -> testet Interaktion von diversen Modulen
- Primär um Fehler zu finden, die beim Zusammenspiel auftreten
- “End-To-End Tests” -> Ebene höher: Testen gesamte Anwendung ( statt Module) –> eher auf Anwendenden-Scope
“Code Knowledge” | Specification-based Testing
- “Black-Box Testing”
- Wir möchten mit unseren Tests gegen eine Spezifikation testen
- Contracts o.ä!
- Wissen über Implementation sollte nicht benötigt werden
Specification-based Testing | Ablauf
![[Pasted image 20240117020031.png]]
Specification-based Testing | Ablauf
- Specification, die gegeben ist, verstehen (i.e Contract | genannte Pre/Post-Conditions)
- Programm anschauen ( wenn möglich!) –> manchmal bekommt man nur die Specifications!
- Partitionen erkennen –> herausfinden, welche Eingaben, welche Ausgaben fordern
Specification-based Testing | Ablauf
def isPositive(n:Int):Boolean
- –> Welche Äquivalenzklassen können wir setzen?
- Randfälle betrachten?
note: Wir wissen anschließend also, dass hier alles >0 true geben muss ( nach Spezifikation!) und alles < 0 nicht positiv was ist mir ? –> positiv oder negativ?
Specification-based Testing | Ablauf
- Mögliche Randfälle betrachten
- Tests schreiben, die unsere Partitionen und Randfälle abdecken wird
- Testen!
Unit Tests | Black-Box Tests | Üben !
[!Task] IM Repo
- Task 2 anschauen und durcharbeiten
- Bearbeite bis zu Subtask 10!
Structure testing | White-Box Testing
- mit Black-Box Spezifikation testen ( ohne Wissen über Implementation)
- mit White-Box –> Implementation testen
- wir möchten alle möglichen Zustände abdecken! ( testen im besten Fall)
- drauf achten, dass alle möglichen (Paths genommen werden)
- weitere Infos ( und Beispiele ) https://se.cs.uni-tuebingen.de/teaching/ws23/se/skript/software-tests/white-box.html
Unit Tests | White-Box Tests | Üben !
[!Task] IM Repo
- Subtask 11 für Aufgabe 2 anschauen und bearbeiten
Metriken |
- Metriken ( jede ) kann man irgendwie betrügen
- Daher ist Coverage nicht immer sinnig
- ( Abhängig von Qualität der Tests )
Metriken |
[!Task] IM REPO
- Aufgabe 3 anschauen und selbständig bearbeiten
- nach 10 min Bearbeitungszeit tragen wir zusammen
Mutation Testing | Prinzip
- Mutation Testing zählt zu White-Box Testing, denn
- Implementation verändert sich! –> SUT wird ( intern ) verändert
- dadurch können neue Zustände auftreten –> Tests sollten diese finden und lösen
- Motivation: Mit “mutierten Implementationen” können wir
- schwache Tests finden
- neue Tests erstellen
- Mutation Testing –> kann die vorherige Metrik invalidieren!
Mutation Testing | Üben
[!Task] IM REPO
- Aufgabe 4 anschauen und selbständig bearbeiten
- nach 20-25 min Bearbeitungszeit tragen wir zusammen
Meta Tests |
- prinzipiell ähnlich / gleich zu Mutation Testing, aber manuell
- also selbst gesetzte Veränderungen in der Implementation
- werden auch in der HW genutzt ( aber nicht einsehbar!)
Meta Tests | Übung
[!Task] IM REPO
- Aufgabe 5 anschauen und selbständig bearbeiten
- nach 10-15 min Bearbeitungszeit tragen wir zusammen
note: what we can draw from this: -> tests might have to change whenever we are changing the implementation itself –> updating it and all might be necessary sometimes!
Property-based Testing
- zuvor bestimmte Äquivalenzklassen (Unit-Testing) geben Beziehungen zwischen Partitionen (Ein/Ausgabe) an
- wir nutzen keine Beispielwerte ( selbst gewählten) –> Generieren von Werten zum testen
- Dafür brauch es:
- Generator –> Erstellt Werte zum Testen für eine bestimmte Partition ( nur negative Zahlen )
- Property –> Assert, der für die Werte aus dem Generator geprüft wird
- –> Generierung kann alle Fälle selbst abdecken, wir müssen sie nicht schreiben!
Property-based Testing | Üben
[!Task] IM REPO
- Aufgabe 5 anschauen und selbständig bearbeiten
- nach 20-25 min Bearbeitungszeit tragen wir zusammen
Feedback
![[Pasted image 20240110124921.png]]
- gerne ausfüllen!