Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mo Jul 14, 2025 01:23

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
BeitragVerfasst: Mo Aug 23, 2010 13:50 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Split by Flash von Thread Texturmanagement, GUI und der Rest des Projekts


zoiX hat geschrieben:
Was genau versteht man eigentlich unter einem "Unit-Test"? Hab das jetzt schon öfter gelesen, kann mir darunter aber irgendwie nicht wirklich was vorstellen. Generell denke ich, du hast Recht - Überplanung tut dem Fortschritt nich wirklich gut :?

Ein Unit-Test ist eine Serie von Funktionen die ein Modul (z.B. eine Klasse) deines Programms automatisch testen. Das sind ganz normale Funktionen die einfach eine Exception werfen wenn der Code nicht wie erwartet reagiert. Üblicherweise benutzt man irgendeine Art von Framework, z.B. JUnit für Java oder QTest als Teil des Qt-Frameworks.

Auch mit Unit-Test findet man natürlich nur die Fehler die man damit testet. Vom Prinzip automatisiert man damit nur das "einfach mal ein paar Werte einsetzen". Für den Anfänger mag das ziemlich sinnlos aussehen aber bei großen Projekten ist es wirklich sinnvoll alles zu testen was irgendwie möglich ist weil man sich dann halbwegs sicher sein kann das bestimmte Funktionen fehlerfrei sind und kann so Fehler schneller eingrenzen.

Hier einfach mal ein Beispiel mit QTest. Die folgenden beiden Test-Funktionen testen die statische Funktion GeomUtil::computeLeastSquaresPlane() die aus einer Menge von Punkten die bestmögliche Ebene berechnen soll. Die erste Test-Funktion liefert Test-Daten, die zweite wird für jeden Satz Test-Daten einmal aufgerufen. QVERIFY ist ein Makro das eine Exception wirft der Ausdruck nicht true ist. Wenn man will kann man auch noch eine sinnvolle Fehlermeldung mitgeben. Die Exception wird dann vom Test-Framework gefangen.

Code:
void TestGeomUtil::testLeastSquaresPlane_data() {
   QTest::addColumn<PointList>("points");
   QTest::addColumn<double>("result");
   QTest::addColumn<double>("deviation");
   typedef CML::Vector3d V3d;
   PointList points;
   double result;
   double deviation;

   points.clear();
   points.push_back(V3d(0,0,0));
   points.push_back(V3d(0,0,1));
   points.push_back(V3d(0,1,0));
   result = 0;
   deviation = CML::EPSILON;
   TestSuite::newRow("1") << points << result << deviation;

   points.clear();
   points.push_back(V3d(-10,-10,-10));
   points.push_back(V3d(-10,-10, 10));
   points.push_back(V3d( 10, 10,-10));
   points.push_back(V3d( 10, 10, 10));
   result = 0;
   deviation = CML::EPSILON;
   TestSuite::newRow("2") << points << result << deviation;


   points.clear();
   points.push_back(V3d(-10, 0,-10));
   points.push_back(V3d(-10, 0, 10));
   points.push_back(V3d( 10, 0,-10));
   points.push_back(V3d( 10, 1, 10));
   result = 0.25;
   deviation = 0.05;
   TestSuite::newRow("3") << points << result << deviation;
}

void TestGeomUtil::testLeastSquaresPlane() {
   QFETCH(PointList, points);
   QFETCH(double, result);
   QFETCH(double, deviation);
   CML::Plane3d plane = GeomUtil::computeLeastSquaresPlane(points);
   PointList::const_iterator itr, end = points.end();
   double sqdistsum = 0;
   for (itr = points.begin(); itr != end; ++itr) {
      double dist = plane * (*itr) + plane.d;
      sqdistsum += dist*dist;
   }
   QVERIFY(CML::abs(result-sqdistsum) <= deviation);
}


Natürlich führt man nicht jeden Test einzeln aus, sondern man gibt dem Framework eine Menge von Testklassen und das Framework ruft automatisch sämtliche Methoden darin auf.
Code:
[coolcat@q9300 bin]$ ./open3dcity-test
PASS : CML::TestVector3::initTestCase()
PASS : CML::TestVector3::testAdd()
PASS : CML::TestVector3::testSub()
(...hab das mal gekürzt...)
PASS : CML::TestVector3::testMatrixMult44()
PASS : CML::TestVector3::testNormalize()
PASS : CML::TestVector3::testLength()
PASS : CML::TestVector3::cleanupTestCase()
PASS : CML::TestPlane3::initTestCase()
PASS : CML::TestPlane3::testProject()
PASS : CML::TestPlane3::cleanupTestCase()
(...hab das mal gekürzt...)
PASS : O3DC::TestXMLUtil::initTestCase()
PASS : O3DC::TestXMLUtil::testParseMatrix44String()
PASS : O3DC::TestXMLUtil::testParseMatrix44StringException()
PASS : O3DC::TestXMLUtil::testBase64Encode()
PASS : O3DC::TestXMLUtil::testBase64Decode()
PASS : O3DC::TestXMLUtil::testToBase64()
PASS : O3DC::TestXMLUtil::testBase64EncodeBinary()
PASS : O3DC::TestXMLUtil::testBase64DecodeBinary()
PASS : O3DC::TestXMLUtil::testZLibDeflateAndInflate()
PASS : O3DC::TestXMLUtil::cleanupTestCase()
-----------------------------------------------------------
Total: 62 tests, 62 passed, 0 failed, 0 skipped
[coolcat@q9300 bin]$

_________________
Yeah! :mrgreen:


Zuletzt geändert von Coolcat am Di Aug 24, 2010 09:51, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 23, 2010 15:55 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Unittests sollte man wirklich kennen. Das ist die Art Test die Entwickler selbst in richtig großen Projekten noch selbst machen müssen (fürs ausführliche Testen gibts da dann eigene Tester).
Hier gibts die pure Definition laut Wikipedia: http://de.wikipedia.org/wiki/Unittest

Einen guten Einblick bietet auch das "GettingStartet" von JUnit. Ist zwar Java, aber die Konzepte werden auch erklärt: http://junit.sourceforge.net/

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 23, 2010 16:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Hi,

also irgendwie hat sich für mich der sinn hinter UnitTests nie wirklich gezeigt...
Also... Ich meine, in dem Beispiel am ende des wiki-artikels unten, wieso sollte ich sowas immer und immer wieder testen?

In 99% der unit tests die ich so gesehen habe bisher wurden immer dinge von mini-funktionen getestet... Das sind in wiederrum 99% der fälle funktionen die man nie wieder anfqsst nachdem sie funktionieren.

Und wirklich komplexe zeichen funktionen etc kann man denke ich mit UnitTests schlecht testen. Meiner Meinung nach wird das alles ein wenig ubertrieben in letzter Zeit mit den UnitTests.

Nen beispiel für nen m.M.n. sinnfreien UnutTest wäre:

int add(int a, int b) {
return a + b;
}

Und ich hab schon ft UnitTests gesehen die genau solche funktionen testen.


Ich regle das in der Regel so, dass wenn ich etwas an einer stelle ändere die ich andernorts schon nutze, ich speziell dafür mir eine kleine test funktion schreibe, also prinzipiell etwas ähnliches wie ein UnitTest, aber eben nur temporär... Und ich denke sowas tut jeder schon seit Jahren in der Programmierung, auch als es das wort "UnitTest" noch nicht gab.

Aya


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 23, 2010 16:55 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Also... Ich meine, in dem Beispiel am ende des wiki-artikels unten, wieso sollte ich sowas immer und immer wieder testen?

Ich denke bei dem Beispiel soll das Übersetzungsmodul getestet werden, nicht die eigentliche Übersetzung. Das ist durchaus sinnvoll, für den Fall das du etwa irgendwann mal etwas an diesem Modul änderst.

Wenn du einmal Code schreibst um etwas zu testen kannst du daraus auch gleich einen Unit-Test machen. Sofern das Test-Framework einmal eingerichtet ist, ist das kein Mehraufwand, häufig sogar weniger Aufwand, weil das Test-Framework ja die Arbeit erleichtert!

Zitat:
Nen beispiel für nen m.M.n. sinnfreien UnutTest wäre:

Die Funktion an sich ist ja schon sinnfrei ;) Ich muss aber zugeben das ich selbst solche trivialen Test-Funktionen habe. Da ist allerdings eher der Sinn das Test-Framework zu testen ;)

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 23, 2010 18:26 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Auf die Gefahr hin, dass ein anderer Mod (Seitenblick zu Flash) das Thema gleich abtrennt:
@Aya: add zu testen ist wirklich sinnbefreit. Aber wenn du dir z.B. nen low-level Record-Stack schreibst, der viel mit Pointern arbeitet und Threadsafe sein soll, kann es hilfreich sein, Push, Pop und isEmpty einigen Tests zu unterziehen. Einfach um jederzeit sicher sein zu können, dass da kein Fehler drin liegt. Es dient hauptsächlich dem Ausschluss beziehungsweise dem Erkennen von Regressionen, würde ich zumindest sagen.

greetings

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Aug 24, 2010 09:44 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
TAK2004 hat geschrieben:
Es gibt mehrere Arten von Tests, wobei der UnitTest nur eine Klasse oder Funktion auf ein- und ausgabe prüft.
Sprich wenn ich meinem Threadpool keinen Thread zuweise, dann sollten Funktion, X,Y und Z garnichts tuen/Fehler werfen/Exceptions werfen/Wert-A zurück geben und wenn ich Threadpriorität änder, sollte diese auch gesetzt werden(wenn sie richtig ist). Also für jeden nur erdenklichen Fall wird ein Test geschrieben. Diese Art von Tests sollte man am besten vor dem Implementieren einer Funktionalität schreiben und dann stück für stück erweitern. Es werden später eh noch Fälle auftreten, die noch nicht beachtet wurden und müssen dann entsprechend nachgetragen werden.
Es gibt dann auch noch Smoke-Tests, Blackbox-Tests und noch einige andere um die höhere Logik zu testen.
libXML2 hat z.B. über 1000 UnitTests und der Code für die UnitTests ist wesentlich größer als der Code für die Bibliothek selber.
Der Sinn dahinter ist das arbeiten im Team und das automatisierte Builden und testen.
Wenn eine Person was kaputtes eincheckt, dann wird dies gebuildet getestet und z.B. alle per E-Mail von dem Fail durch Person-XY benachrichtigt und entsprechend kann die Person oder jemand anderes schnell reagieren und das Repo wieder in ein working status versetzen.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Aug 24, 2010 09:51 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Auch kleine Sachen zu testen ist nicht verkehrt. Es kostet nur minimal Zeit, weil die Tests meist genauso trivial sind wie funktion selbst. Und die Mathematiker hier, werden dir sicher von einem Fall berichten können, was passiert, wenn man feststellt, dass die Basisfunktionen (Axiome), von deren Korrektheit man seit ewigen Zeit einfach ausgeht, nicht stimmen. Das wäre "nicht schön".

Bei den Unittests wird das einmal geschrieben, und läuft einfach mit durch. Also wieso drauf verzichten, wenn man diese Sicherheit quasi geschenkt bekommt?

Achja: Wieso gibts es manchmal so kleine Tests überhaupt, wo man doch in den Projekten meist nur so wenig Zeit hat? Ganz einfach: Der Kunde kann bei Projektstart mit dem Entwickelnden Unternehmen eine bestimmte Codequalität Vertraglich festgelegt haben. Und da steht dann meist auch was zu den Erfüllungsmaßstäben, wie z.B. Kommentarqualität (alle public Funktionen müssen über Kommentare verfügen inkl. Parameterkommentar, Returnwert und ob die Parameter entfallen können), oder halt auch eine Prozentuale Testabdeckung durch Unittests (da gibts ja Tools um diese zu ermitteln).

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 25, 2010 07:28 
Offline
Fels i.d. Brandung
Benutzeravatar

Registriert: Sa Mai 04, 2002 19:48
Beiträge: 3830
Wohnort: Tespe (nahe Hamburg)
Wobei auch das Konzept des "Test Driven Development" in den Raum geworfen werden sollte, der einen pragmatischen Entwicklungsansatz feststellt. Anstatt Dir nur im Kopf zu überlegen, wie etwas aussehen soll, formulierst Du zunächst über den Test, welche Ergebnisse eine Funktion zur Verfügung stellen soll. Ist der Test formuliert, beginnst Du mit der Implementierung und kannst daran validieren, ob das Ergebnis zutrifft. Gerade auch im Hobby-Bereich vermutlich ein geschickter Weg wenig für den Papierkorb zu arbeiten und die Planung gleich mit etwas sinnvollen zu verbinden.

Wie immer gilt: Nicht jedes Projekt wird von einem 1-Mann-Team betreut. Intensives Testen (IMAO auch von Low-Level-Funktionen!) sind extrem wichtig. Es gibt nichts schlimmeres als ein Brown-Field-Projekt, dass nicht ausreichend getestet wird und mit jeder noch so geringen Veränderung Regressionen verursacht. Nicht immer sind die Ergebnisse von Methoden so eindeutig, dass sie sich direkt aus dem Kontext ergeben. Ein Test ermöglicht es sicher zu stellen, dass ein Ergebnis weiterhin geliefert werden kann. Größere Projekte sollten heutzutage hoffentlich nicht mehr ohne ein entsprechendes Framework von Tests abgenommen werden, da diese überspitzt gesagt einen Teil der Dokumentation darstellen können. Auch wenn es zunächst nach mehr Aufwand aussieht, hat man den i.d.R. meist sehr schnell wieder rausgeholt. Zu dem Thema gibt es auch ein reichhaltiges Angebot an Literatur.

_________________
"Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 25, 2010 10:29 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Hi,

okay ich habe noch nie in einem Team gearbeitet wo jede immer an allem rumbastelt. Das war bisher immer so, dass ein Programm einfsch in module geteilt wurde und die von jeweils einzelnen leuten gemacht wurden.

Mein Arbeitsumfeld ist aber nawtürlich auch ein komplett anderes als eures. Hier haben die Chefs der Firma NULL Ahnung vom Programmieren etc, dementsprechend ist den Programmierern narrenfreiheit gelassen.

Für die Firma und Produktion hier zählt nur das etwas schnell fertig wird. Es kommt nicht selten vor das jemand kommt "Hilfe, Hilfe wir brauche für den shot so und so etw um den XYZ Effekt hinzubekommen! Schaffst du das heute noch?"

Sprich es geht darum das schnell ein ergebnis geliefert wird.

Bei dem großen Projekt wo ich immer dran Arbeite wenn grad nix anderes wichtigeres da ist würde mir aber auch nicht einfallen wo ich da UnitTests machen sollte.. Genauso bei meinem Framework welches ich zu hause bastel. Da kommt es durchaus vor das ich mal an einer funktion was ändere welche schon an 1000 stellen benutzt wird, aber... Ka, da reicht mein denk vermögen etc aus, dass ich weiß was sie vorher zurück gegeben hat um das wieder so zu machen.

Ein gutes beispiel wäre meine Bitmap-Klasse welche ich überall benutzt wo es um Bilder geht , trotzdem hab ich die über die zeit 3-4 mal komplett neu geschrieben weil mir durch die gewachsene erfahrung immer neue wege einfieke wie ich etwas effektiever lösen kann.

Anfangs konnte die Klasse nur 8bit RGBA, jetzt kann sie beliebig viele Channels von beliebigem typ haben etc. Und das alles habe ich ohne irgendwelche UnitTests problemlos hinbekommen.


Also was ich sagen will: Ich kann es durchaus verstehen das UnitTests praktisch sind wenn man fremd-source bekommt und da fehler finden muß etc. aber fur meinen privat gebrauch und solange ich an dingen alleine Arbeite seh ich für mich persönlich keinen nutzen darin.

Aya


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 26, 2010 11:26 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Das hat mit Unit-Test auch wenig zu tun, wie gut dein Klassen-Design ist.
Der Unit-Test ist zum sicher sein, das dein Code nicht fehlerhaft ist, wo Klassen-Design viel einfluss hat.
Gute Fehlerquellen in C++ sind Threads, Sockets, Pointer und Exceptions.

http://nopaste.info/dbfabf5fd1.html Hier mal ein Unit-Test aus mein Framework.
Dieses wird von meinem Buildsystem automatisch compiliert und ausgeführt, sobald ich im SVN eine Änderung mache.
Das Ergebnis kann ich dann einsehen und weiß, ah die Änderung an der Stringklasse hat mir Funktion a,b und c in Modul Netzwerk, sowie d und e in Modul WPF zerlegt und muss entweder gefixt oder rückgängig gemacht werden, da sonnst Software nicht mehr korrekt laufen würde.

Deine Bitmap Klasse ist genau so ein Kandidat, der so viele Nutzer an sich bindet, dass nur geringste Änderungen das ganze Programm unbrauchbar machen und das nicht mal auffallen muss, bis man mal eine der betroffenen Funktionen nutzt.

In mein Praktikum bei Yager waren der Buildprozess noch viel schärfer eingestellt, der hat keine installations-Pakete generiert, solange nur ein einziger Test fehl schlug.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Sep 18, 2010 07:47 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 27, 2005 12:44
Beiträge: 393
Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo,

Unittests sind vor allem zum Testen von Logik gut. Man muss nicht unbedingt eine Funktion testen die a + b berechnet, aber wenn es etwas komplexer wird, sollte man alle mögliche Fälle (Eingabeparameter) einmal getestet haben (Überdeckungstest). Positiver Nebeneffekt beim Schreiben von Unittests ist, dass man anfängt seinen Quellcode aufzuräumen. Kleine Funktionen mit wenig Logik lassen sich besser testen als Methoden mit mehreren hundert Zeilen Code!

Ansonsten sind Unittests noch bei Datenbankzugriffen sinnvoll. Häufig kommt es vor, dass man das Datenmodell ändert und vergisst den Quellcode anzupassen.

Für Java gibt es als Alternative zu JUnit noch TestNG und für Webentwicklung Spock.

Viele Grüße
djehut1

_________________
Wenn Gauß heute lebte, wäre er ein Hacker.
Peter Sarnak, Professor an der Princeton University


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Jan 02, 2011 20:29 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Ahoi,

ich bin der Meinung, dass Unittests nicht nur in Teams, wo queerbeet gearbeitet wird, nützlich sind (Nützlich = Nutzen > Aufwand), sondern auch für einen einzelnen Entwickler vorteilhaft sind.
Wenn man sich die vielen Beispiele im Netz zu Unit-Tests anschaut, wo, wie Aya auch bemerkt hat, simple Sachen wie ein "add" völlig unmotiviert getestet werden, bringen Unittests bzw. Integrationstests wirklich nahezu nichts.

Wenn die Dinger aber richtig (Und die Definition von "richtig" überspringe ich mal, da sich die Frage hier m.E. um den Nutzen dreht) eingesetzt werden, ergibt sich folgendes (Ich dachte eigentlich, dass ich das auch schonmal irgendwo im Forum zusammengeschrieben hätte... hm):
  • Sicherheit vor Refactoring-Fehlern
  • Dokumentation des getesteten Codes
  • Simplere APIs / klarere Klassenstruktur
  • Ein Argumentationsmittel ggü. dem Vorgesetzten
  • Noch einiges mehr, die Liste erhebt keineswegs einen Anspruch auf Vollständigkeit

Natürlich ergeben sich nicht alle diese Effekte bei jedem Projekt im gleichen Maße. Und manche davon sind auch gleichzeitig Vorbedingung für gute Tests. Wie z.B. eine gute Klassenstruktur (Stichwort: Testability, Testbarkeit): Wenn man einen riesen Haufen Klassen hat, der komplett selbstständig ohne jeglichen Input von außen (Blackbox) irgendwas macht, hat man meist keine Chance auf Testbarkeit, da die Klassen dann nur über Seiteneffekte agieren und sowas ist generell schlecht / unmöglich sinnvoll zu testen. Nicht sinnvoll heißt: Entweder wird der Aufwand gigantisch oder der Nutzen minimal.
Wenn man dagegen Code hat, der es relativ leicht ermöglicht, die Verhaltensweise punktuell zu ändern, hat man damit i.d.R. eine hohe Testbarkeit und zwingend modularen Code. Und wie wir alle wissen: Modularer Code = gut ;)

Die Dokumentation dagegen ist etwas, was sich bei einigermaßen sinnvoll benannten Tests automatisch ergibt. Gegenüber der traditionellen Dokumentation von Code in Form von Inline-Kommentaren, API-Docs, Wikipages etc. haben Tests einen entscheidenden Vorteil: Sie sind garantiert aktuell. Sie zeigen zu 100% wie der Code zu benutzen ist und je höher die Testabdeckung ist, umso höher sind auch die dadurch dokumentierten Anwendungsfälle (Usecases). Jemand, der die Tests durchliest, sieht automatisch, wie der Code zu benutzen ist und hat Tonnen von Beispielen. Wenn dann noch die Methoden und Klassen aussagekräftig benannt sind, spart das 98% der API-Dokumentation (Stichwort: Clean Code).

Damit komm ich auch gleich zum Punk Refactoring: Der Vorteil erübrigt sich natürlich, wenn man gar kein Refactoring macht. Wer also tatsächlich Code schreibt und ihn dann über die Monate kein einziges Mal wieder anfasst, ist also entweder ein Programmiergott (Und nichtmal Linux Torvalds schreibt auf Anhieb 100% perfekten Code)... oder eben nicht ;)
Wer also Refactoring betreibt, steht vor dem Problem, dass er dadurch potentiell Fehler in den Code einbauen könnte (Wenngleich natürlich unterm Strich durch gutes Refactoring mehr Fehler behoben und entlarvt als verursacht werden). Diesem Problem kann sehr effektiv durch Unit-Tests begegnet werden, da diese einem durch einen einzelnen Mausklick Auskunft darüber geben, ob der Code noch so funktioniert, wie er soll, oder ob er das nicht mehr tut.

Auch einen weiteren Aspekt, den der Argumentationsbasis, sollte man nicht außer Acht lassen: Hat man eine umfangreiche Suite an Tests, kann man damit argumentieren. Man kann damit zwar nicht beweisen, dass der Code fehlerfrei funktioniert, dennoch ist es weit mehr als ein bloßes Indiz darauf. So ziemlich jeder Projektleiter freut sich über gute und umfangreiche Tests, geben diese doch Auskunft darüber, wie weit das Projekt schon vorrangeschritten ist, wie wahrscheinlich das Auftreten von Fehlern ist, usw.. Wenn man nun (z.B. mit Hilfe von Metriken zur Testabdeckung, Stichwort Code Coverage) belegen kann, dass man viel getestet hat, dabei aber sehr wenig Fehler auftraten, kann man damit seine Qualitäten als Entwickler / Team begründen. Und das ist dann möglicherweise mit ner Gehaltserhöhung verbunden.


So, ich denke, die Liste war erstmal lang genug. Ich selber verwende ja in meinem Hobby-Spielchen ebenfalls recht ausführliche Unittests. Und selbst dort (obwohl es einen recht begrenzten Umfang hat und alles andere als wahnsinnig komplex ist), hat es mir an einigen Stellen bereits die Augen geöffnet und geholfen, besseren Code zu schreiben.

Und so will ich enden mit einer kleinen Empfehlung meinerseits für die Java-Welt: Wer die JUnit-Assertions oder selbst die von TestNG (Was übrigens ein geniales Testframework für Java ist) zu begrenzt bzw. zu kompliziert und irreführend findet, dem seien die FEST Assertions ans Herz gelegt:
Code:
  int removed = employees.removeFired();
  assertThat(removed).isZero();
 
  List<Employee> newEmployees = employees.hired(TODAY);
  assertThat(newEmployees).hasSize(6)
                          .contains(frodo, sam);
 
  assertThat(yoda).isInstanceOf(Jedi.class)
                  .isEqualTo(foundJedi)
                  .isNotEqualTo(foundSith);

(Von der oben verlinkten FEST Website geklaut)

Die Jungs hinter FEST haben auch was ganz ähnliches für Java Reflection geschrieben, womit man in den Tests einfach Reflection verwenden kann, ohne sich um die tausenden checked Exceptions kümmern zu müssen. (Exceptions sind gut, Checked Exceptions nicht).

Hope this helps,
~ Frase

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jan 03, 2011 07:21 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 11, 2009 08:02
Beiträge: 532
Programmiersprache: pascal (Delphi 7)
Verständnisfrage: Wie funktionieren diese Tests? Also, man lasst die Funktion rechnen, und schaut nach, ob dabei das richtige rauskommt. Woher weiß man, was das richtige Ergebnis ist? Nämlich ohne es auszurechnen. Bei simplen mathemathischen Funktionen könnte ich mir noch vorstellen, dass man einfach die Grenzfälle testet, die sich exakt berechnen lassen, aber sonst?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jan 03, 2011 10:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
So läuft das eigentlich, man nimmt konstante eingaben und prüft die Ausgabe mit ein vorgerechnetem Ergebnis.
Hier mal ein kleiner Beispiel Test für die Quaternion Methode Slerp.
Code:
Bool Slerp()
      {
         Quaternion<Float32> q(1,0,0,0);
         Quaternion<Float32> q1(0,0,0,1);
         Quaternion<Float32> q2(0.7071067811865475,0,0,0.7071067811865475);
         Quaternion<Float32> q3;
         q3=q.Slerp(q1,0.5);
         return Math<Float32>::IsAlmostEqual(&q3[0],&q2[0],4);
      }

IsAlmostEqual ist eine Behilfsfunktion, welche über Epsilon prüft ob 2 Gleitkomma Werte den gleichen Wert repräsentieren(== wäre falsch).

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jan 03, 2011 11:36 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
sharkman hat geschrieben:
Verständnisfrage: Wie funktionieren diese Tests? Also, man lasst die Funktion rechnen, und schaut nach, ob dabei das richtige rauskommt. Woher weiß man, was das richtige Ergebnis ist? Nämlich ohne es auszurechnen. Bei simplen mathemathischen Funktionen könnte ich mir noch vorstellen, dass man einfach die Grenzfälle testet, die sich exakt berechnen lassen, aber sonst?

Das ist tatsächlich eine sehr gute Frage. Die von tak gezeigt Variante ist nur eine von vielen, allerdings die simpelste.
Wenn man etwas umfangreiche Tests hat, sollte man den eigentlichen Test und dessen Eingabeparameter trennen. In JUnit und den meisten anderen Testframeworks muss man das über die gewohnte Heraustrennung von Spaghetticode in eine Methode mit Parametern machen. Selbige ruft man dann im Test einfach auf.
TestNG (und das ist mit der Hauptgrund, warum es TestNG überhaupt gibt) hat dafür eigene, explizite Wege (DataProvider):
Code:
@DataProvider
public Object[][] someDeadPeople() { // Das ist wirklich nur ein zweidimensionales Array von Objekten.
    return new Object[][] {
        {"Bob", "Marley"},
        {"Michael", "Jackson"},
        {"Urban", "Priol"}
    };
}

@Test(dataProvider = "someDeadPeople")
public void deadPeopleShouldBeConsideredDead(String firstName, String lastName) {
    // Disclaimer: Der Code wird natürlich horrende schief laufen, wenn livingPeople.get(lastName) bereits null liefert
    assertThat(livingPeople.get(lastName).get(firstName)).isNull();
}


Damit hat man das wunderbar herausgetrennt und bekommt dafür im Testbericht auch schön aufgeführt, mit welchen Parametern die jeweilige Testmethode aufgerufen wurde. Sieht also etwa so aus:
Code:
com.example.people.PeopleTest.deadPeopleShouldBeConsideredDead(Bob, Marley): PASSED
com.example.people.PeopleTest.deadPeopleShouldBeConsideredDead(Michael, Jackson): PASSED
com.example.people.PeopleTest.deadPeopleShouldBeConsideredDead(Urban, Priol): FAILED
    caused by: org.fest.assert.AssertionNotNullException: value Human(Urban, Priol) is not null at PeopleTest:42

So in der Art.

Neben explizit aufgeschriebenen Parametern kann man diese auch generieren lassen (Stichwort: ScalaCheck). Das ist beispielsweise gut für Grenzwerte und ähnliches. Wenn man beispielsweise weiß, dass sich der Code für alle Zahlen zwischen z.B. 0 und 65534 exakt gleich verhalten soll, kann man die Zahlen dazwischen generieren lassen (oder auch nur ein paar davon, stichpunktartig) usw. Da gibt's einige Möglichkeiten, die den Rahmen des Threads hier sprengen würden.

Allen gemeinsam ist, dass man sich bewusst sein muss, was der Code, den man testet, eigentlich machen soll. Du schreibst in Form der Tests also letztendlich hin, was im Endeffekt passieren soll. Und wenn man das einigermaßen durchzieht, bekommt man sogar eine Spezifikation, die genau sagt, was der Code macht.
Das geht sogar so weit, dass einige Testframeworks sich darauf spezialisiert haben. Das von mir eingesetzte specs z.B. ist so ein Behavior Driven Development (kurz: BDD) Testframework. Dort spezifiziert man das Verhalten der Software. Im Endeffekt sind das Unittests in Grün. Mir persönlich gefällt die Syntax besser, darum hab ich das genommen.
Kleines Beispiel gibt's bei mir im Code von Swift Steel. Der verlinkte Test macht sich auch das zunutze, was tak vorhin als Epsilon-Methode bezeichnet hat. (isNearTo bei mir). Die Spezifikation gibt an, wie der Code Nachkommastellen berechnen können soll. Ich hätte an der Stelle übrigens auch Testfälle generieren können:
Code:
object DecimalPlaceSpec extends YangSpec {
  "The decimal place" should {
    "be calculated correctly for .6" in {
      DecimalPlace of 3.6 must beNearTo (.6)
    }
//...



So, der Post ist nun glaub ich lang genug ;)
~ Frase

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: Bing [Bot] und 3 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.012s | 17 Queries | GZIP : On ]