Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

1

08.02.2014, 18:29

Unit test

Guten Tag,

ich soll für nächste Woche einen Vortrag über Unit Test halten. Nach dem ich mich ein wenig eingelesen habe muss ich zugeben das ich weder richtig verstanden habe wie man Unit Test einsetzt noch wofür sie genau gut sind.
Mit Unit Test werden doch bestimmte Teile eines Programs getestet, aber ist es denn nicht viel mehr aufwand einen Test für einen Algorithmus zu schreiben als ihn in der Anwendung zu testen? ich weiß doch nicht immer was genau bei einem Algorithmus am Ende raus kommt.


Wann sollte man ein Unit test einsetzten und wie macht man das?
Warum gibt es verschiedene Arten von Unit Test und wo sind ihre Unterschiede?

Ich bedanke mich schon einmal bei euch

2

08.02.2014, 18:49

Gerne wird zusammen mit Unittests Test-Driven-Development genannt.

Sinn des ganzen sei, dass man die Tests schreibst, bevor es an die eigentliche Implementierung geht.

In meiner Signatur findest Du eine (sehr kleine) Python-Bibliothek namens weakcallable. Dort habe ich TDD ziemlich exzessiv betrieben.

Und man weiß natürlich was am Ende eines Algorithmus heraus kommt.

Zitat

Ich bin nicht der Messias.
Ich sage, du bist es, Herr. Und ich muss es wissen, denn ich bin schon einigen gefolgt.

https://bitbucket.org/bwbg

3

08.02.2014, 18:54

aber ist es denn nicht viel mehr aufwand einen Test für einen Algorithmus zu schreiben als ihn in der Anwendung zu testen?
Wenn dein Programm aus 3 Funktionen besteht, ja. In der Regel wird deine Software mit der Zeit immer unüberschaubarer. Wenn du irgendwann 500 oder mehr Tests hast, willst du natürlich nicht bei jedem neuen Feature manuell testen müssen, ob die vorherigen 499 Features noch funktionieren oder durch einen Nebeneffekt nun 'buggy' sind. Unit Tests liefern dir in einer Sekunde direktes Feedback. Außerdem helfen sie bei der Entwicklung: wenn ich mir vorher Tests definiere und so das Verhalten für meine zukünftigen Komponenten festlege (TDD), vermeide ich erfahrungsgemäß viele Fehler.

€: In Jave gibt es JUnit, in C# gibt es MSTest oder NUnit als UnitTests. Neben UnitTests gibt es auch Migrationstets, Integrationstests und Oberflächentests. Weitere wichtige Stichworte: Testfallkatalog, Testprotokoll, Continuous Integration.

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

4

08.02.2014, 19:09

Zusätzlich zu dem, was bereits schon geschrieben wurde sind Unit-Tests auch ziemlich praktisch, wenn du mal den zugrundeliegenden Algorithmus ändern willst.

Zum Beispiel, wenn du für ein Problem schon eine Lösung hast, aber die aus irgendwelchen Gründen geändert werden muss (zu langsam, zu viel Speicherverbrauch, etc). Dann hast du durch die Unittests schon die ganzen Grenzwerte abgedeckt und du kannst dich dementsprechend in der restlichen Anwendung darauf verlassen, dass dein Code auf eine bestimmte Art und Weise funktioniert.

Wenn du jetzt also den Algorithmus dahinter änderst siehst du so auch direkt, ob sich das Verhalten in deinen Grenzfällen geändert hat und sich das Verhalten nicht irgendwo irgendwie geändert hat, was sich auf andere Dinge auswirken könnte.

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

5

08.02.2014, 19:12

Danke schon einmal,
das Test-Driven-Development finde ich interessant.
Und man weiß natürlich was am Ende eines Algorithmus heraus kommt.

Wenn ich weiß was ich rein tue dann schon aber die meisten Programme sind doch auf eingaben eines Benutzers angewiesen, da kann ich doch nicht vorher sehen was er tut und was er nicht tut.

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

6

08.02.2014, 19:15

Wenn ich weiß was ich rein tue dann schon aber die meisten Programme sind doch auf eingaben eines Benutzers angewiesen, da kann ich doch nicht vorher sehen was er tut und was er nicht tut.


Du musst ja auch nicht für alle möglichen Eingaben testen. Du testest was an den Grenzbereichen (zu große Zahlen => overflow, leere Daten, etc) passiert.
Wenn die Addition von 3 und 5 klappt, dann wird das sicherlich auch mit 12 und 182 tun. Wenn nicht, dann hast du einen zusätzlichen Testfall, denn du schreibst und die Funktion dementsprechend verbesserst.

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

7

09.02.2014, 10:17

Danke schon einmal,
das Test-Driven-Development finde ich interessant.
Und man weiß natürlich was am Ende eines Algorithmus heraus kommt.

Wenn ich weiß was ich rein tue dann schon aber die meisten Programme sind doch auf eingaben eines Benutzers angewiesen, da kann ich doch nicht vorher sehen was er tut und was er nicht tut.


Dazu hat mal jemand sinngemäß gesagt, dass es immer noch besser ist unvollständige Tests zu schreiben als gar keine.

Und Benutzereingaben machen automatische Tests durchaus schnell recht aufwendig. Mit Unittests kann man besonders die ganzen Algorithmen die im Hintergrund werkeln automatisch testen. Da gibt es dann Tools wie z.B. http://www.ranorex.de/
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

10.02.2014, 11:25

Wenn ein Algorithmus implementiert werden soll, dann steht bereits vorher dessen Eingabe (bspw. 1 String oder 2 Zahlen oder 2 Kreise oder ...) und dessen Ausgabe (bspw. String, Zahl, Wahrheitswert, geometrische Figur, ...) fest.Anhand der (gewünschten) Funktionsweise des Algorithmus kann man nun Testfälle suchen, die die bereits erwähnten Grenzwerte darstellen.

Will man bspw. 2 Kreise auf Überschneidung prüfen, wird true zurückgegeben, wenn sich die beiden übergebenen Kreise überschneiden und false wenn nicht. 2 Kreise überlagern sich, wenn der Abstand ihrer Mittelpunkte geringer als die Summe der Radien ist.
Übergibt man also 2 Kreise, die auf einer Achse gleich sind und auf der anderen einen Abstand besitzen, der der Summe der Radien entspricht, sollte man flase erhalten, bei 2 Kreisen mit dichterer Positionierung sollte man true erhalten. Hieraus resultieren also bereits die ersten beiden Testfälle: geringstmöglicher Abstand ohne Überschneidung und größtmöglicher Abstand mit Überschneidung.
Kreise haben im Gegensatz zu Quadraten mit gleicher Breite und Höhe keine Ecken, also können 2 Kreise diagonal wesentlich dichter zusammen liegen, als es 2 achsenausgerichtete Quadrate. Hier könnte man also noch ein paar Testfälle schreiben, bei denen die Kreise diagonal sich einerseits nicht überschneiden und so dicht wie möglich beieinander liegen und andererseits überschneiden und so weit wie möglich entfernt voneinander liegen. (Hierbei sollte man aber die Genauigkeit der jeweilig verwendeten Datentypen berücksichtigen.)
Da die Kreise unterschiedliche Größen haben können, muss man die ganzen Test auch mit verschiedenen Größenordnungen durchführen, wodurch für jeden bisher erstellen Testfall noch min. 1 weiterer erstellt werden kann.
In diesem Beispiel hat man also min. 8 Testfälle, zur Sicherheit könnte man aber auch noch weitere Tests einfügen, die nicht nur die Grenzwerte abdecken, wodurch man, wenn man will, auch 32 Testfälle haben kann.

In einem Unittest erzeugt man sich grundsätzlich für jeden Anwendungsfall erst einmal die Ausgangssituation (im oberen Beispiel je 2 Kreise), ruft die entsprechende Funktionalität auf und wertet das Ergebnis aus (im oberen Beispiel: vergleich der Rückgabe mit erwarteter Rückgabe). Idealerweise muss man dadurch nur sehr viele Codezeilen durch Copy&Paste erzeugen und die entsprechenden Werte anpassen. (Zudem schreibt man diese meist ein einziges Mal und hat diese dann, während man andernfalls, wie bereits beschrieben, den Test manuell mehrmals wiederholen muss.) Komplizierter (zu schreiben) werden Unittests genau dann, wenn das System, dessen Funktionalitäten getestet werden sollen, in sich zu viele Abhängigkeiten vorhanden sind und zu wenig entkoppelt wurde. Erwartet eine Methode zum Speichern von Daten einen Stream, kann während des Tests eine Implementierung verwendet werden, die die zu schreibenden Daten intern vorhält, damit diese später mit den erwarteten Ergebnissen verglichen werden können. Würde es keine solche Methode geben, sondern nur solche, die bspw. den Dateinamen entgegennehmen, müsste man die Datei wieder auslesen, was "ungetesteten" Code erfordern würde, wodurch der Test an und für sich unsinnig wäre.

Benutzereingaben:
Es kommt ganz darauf an, was der Benutzer eingeben kann, allerdings wird der Test dann i. d. R. nicht die Oberfläche bedienen, sondern den Code aufrufen, der im Hintergurnd mit den Benutzereingaben gespeist wird. Und dann hat man wieder Grenzwerte (des Algorithmus), die man abdecken kann. (Sollte etwas anderes gemeint sein, wäre eine Beschreibung dessen hilfreich.)


Ich muss zugeben, dass ich Unit-Tests bisher noch nicht übermäßig verwendet habe, allerdings kann ich von den Situationen, in denen ich diese verwenden konnte, sagen, dass es sich durchaus gelohnt hat.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Tobiking

1x Rätselkönig

  • Private Nachricht senden

9

10.02.2014, 12:29

Komplizierter (zu schreiben) werden Unittests genau dann, wenn das System, dessen Funktionalitäten getestet werden sollen, in sich zu viele Abhängigkeiten vorhanden sind und zu wenig entkoppelt wurde.

Deswegen hat uns TDD in einem Projekt sehr geholfen. Es setzt eine gewisse Mindestqualität für den Code voraus um ordentlich verwendbar zu sein. Wir hatten da jemanden im Team der aus Bequemlichkeit auf Interfaces verzichtet und häufig Singletons genutzt hat. Nachdem dieser 1-2 Tests schreiben musste und sich da dermaßen einen abgebrochen hat um diese zum Laufen zu bekommen konnte er umgestimmt werden. Mit einem ordentlichen Framework für Dependency Injection und Mocking ist der Mehraufwand auch echt überschaubar.

Werbeanzeige