| 

.NET C# Java Javascript Exception

3
Sollte man immer eine Testabdeckung von 100% anstreben?

Falls ja, wie testet man private Methoden?
Kann man/Wie Methoden Methoden ohne Rückgabewert testeten?
News:
13.10.2009
ermin 1,3k 2 7
8 Antworten
4
Getestet werden soll das API - also das was von außen sichtbar ist. Private Methoden gehören da nicht dazu.

Bei Methoden ohne Rückgabewerte wird getestet ob die übergebenen Argumente keinen Fehler/einen erwarteten Fehler auslösen.

Wenn 100% Testabdeckung vorhanden dann kann man sicher dass 100% des Codes getestet sind ;) Wenn schon getestet wird dann ordentlich und somit sollten die 100% angestrebt werden.

Anmerkung: Private Methoden können durch die Tests insofern berücksichtigt werden da sie von öffentlichen Methoden aufgerufen werden.

Edit: Für .net gibt es mit PEX ein Test-Framework das versucht 100% des Codes zu testen.
13.10.2009
gfoidl 9,4k 3 5
gfoidl 9,4k 3 5
2
Gibt es bei C# nicht noch ein Attribut womit man private Methoden zugänglich machen kann?
GENiALi 14.10.2009
2
Für C# weiss ich es nicht, aber mit Java geht das. Würde ich aber keinem empfehlen, da die meisten das nur missbrauchen.
keinhaar 14.10.2009
1
In C# würde es per Reflektion gehen. Aber siehe keinhaar's Anmerkung -> Missbrauchgefahr
gfoidl 14.10.2009
Wie sieht es mit Gettern und Settern aus? Ist es nötig solche trivialitäten wirklich testen?
ermin 14.10.2009
1
Wenn über eine Eigenschaft (Getter, Setter) nur ein Feld gelesen/geschrieben wird erspare ich mir das ;)

Wird in der Eigenschaft lazy loading/evaluation umgesetzt dann wirds getestet.
gfoidl 14.10.2009
@keinhaar: meinst du reflections?
LastFreeNickname 14.10.2009
Hi, ich teste private Methoden nicht. Wenn es Methoden sind die wichtig sind getestet zu werden setze ich sie auf internal und mache sie mit Hilfe des Attributes InternalsVisibleTo meinem Testprojekt zugänglich
Nicolai Schönberg 05.04.2012
5
100% Testabdeckung ist Dummgeschwätz aus Marketing, Vertrieb und Management.

Definition: Testabdeckung ist das Verhältnis von gemachten Tests zu theoretisch möglichen Tests
Wiki Testabdeckung

Selbst bei einfachsten Applikationen würden die Testzeiten ins Unermessliche gehen.
Wenn eine Applikation/Methode beispielsweise 100 verschiedene binäre Zustände hätte, so müßte also 2¹⁰⁰ Tests gefahren werden.
Angenommen man könnte pro Sekunde 1000000 Tests durchführen, dann braucht der Test 40200 Milliarden Jahre. Zur Erinnerung, das Alter des Universums wird auch 15 Milliarden Jahre geschätzt.

Eine Methode die 3 32 Bitwerte annimmt, kann auf 2⁹⁶ verschiedene Arten aufgerufen werden.
Bei einer Methode mit einem String der IMMER genau 6 Zeichen lang ist, ergeben sich ebenfalls 2⁹⁶ verschiedene Aufrufe.

Selbst bei einfachsten Anwendungen tendiert die Testabdeckung IMMER gegen 0
02.11.2009
stefan.bachert 395 4
Sehr guter Einwand.
gfoidl 02.11.2009
Etwas zu hart formuliert, aber der Kern stimmt. Wobei ich hinzufügen muss, dass die kombinatorische Explosion natürlich auf einem "naiven" Ansatz basiert. Man verwendet ja spezifisches Wissen, um Tests effizient aufzubauen und sich auf die Parameter-Werte zu konzentrieren, bei denen man eine Verhaltensänderung erwarten würde. Dann kommt man auch mit weniger auf 100% C0-Abdeckung.
LastFreeNickname 05.11.2009
Wenn man internes Wissen verwendet, dann ist das möglicherweise bei nächsten Release wieder hinfällig und damit falsch.

100% Testabdeckung sind einfach nicht drin. Damit muss man sich abfinden. Man kann einige Fälle durchlaufen lassen und das war es.

Man kann dafür sorgen dass wenigstens jede Codezeile einmal aufgerufen wurde, aber besonders aussagefähig ist das nicht. Es weckt nur die trügerische Illusion wie in "ich bin hier schon mal unfallfrei vorbei gefahren also fahre ich hier immer unfallfrei"
stefan.bachert 09.05.2010
4
Beim Testen würde ich immer drauf achten, was sinnvoll ist, und dann aus reiner Paranoia noch ein bißchen mehr machen. Das schwierigste ist natürlich herauszufinden, was für deine Klasse / Anwendung sinnvoll ist und wieviel Aufwand du zum Testen treiben willst, also bildhaft der Unterschied zwischen Textausgabe und der zentralen, kritischen Flughafensteuerung.

Grundsätzlich unterscheidet man zwischen verschiedenen Abdeckungscharakteristiken. Wikipedia liefert da ganz gute Basisinformationen, ansonsten empfehle ich nach Fachliteratur und Vorlesungsfolien zum Thema zu suchen.

Zu der Frage, was sinnvoll ist, würde ich natürlich beim Zweck der Klasse starten - also was soll sie tun und welche Sonderfälle gibt es. Die 100%-Zeilenabdeckung (C0-Test) sollten sich durch reine Variation der Parameter und des Objektzustands erreichen lassen, ansonsten hast du quasi toten Code. Wenn du das im Kopf durchgehst, ergeben sich dadurch schon eine Menge Testszenarien. Gerade auf die Grenzwerte, also ab wann würde ich eine Änderung im Verhalten erwarten, würde ich mich konzentrieren. Ebenfalls nicht zu unterschätzen sind Negativtests. Wie verhält sich die Software bei gezielt falschen Eingaben und wann werden Exceptions geworfen bzw. gefangen?

Zu der private-Problematik: Überprüf doch mal, ob du die Methoden nicht auch als static deklarieren kannst. Spricht für gutes Design und erlaubt einfaches Testen. :-)
14.10.2009
LastFreeNickname 316 1 7
1
Dass static gutes Design würde ich nicht pauschal stehen lassen - kann sein muss aber nicht ;)
gfoidl 14.10.2009
Absolut richtig! :-)
Meinte damit, dass es dort, wo es gemacht werden kann, auch überlegt werden sollte. Wenn es dann Sinn macht, spricht das für gutes Design.
LastFreeNickname 14.10.2009
1
Seit ich diese Frage gelesen habe, gehen mir das Thema und die daraus folgenden Probleme nicht mehr aus dem Sinn ;-)

100% Codeabdeckung durch Tests finde ich gut und richtig, wie aber bekomme ich das z.B. hier hin?

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;

try {
final Document doc = DocumentBuilderFactory.newInstance().
newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
// egal, was auch immer ...
e.printStackTrace();
}


Sicher doch nicht, indem ich die Verantwortung abwälze und die Exception einfach werfe (um dieser Antwort schon mal vorzugreifen)?

Nachtrag zur Verdeutlichung:

InputStream stream = new ByteArrayInputStream("foo".getBytes());
try {
stream.read();
} catch (IOException e){
; // hier komme ich nie hin
}


stream.read() wirft eine IOException, da ich versuche, sauber zu designen und gegen Interfaces zu programmieren, statt gegen Implementierungen. Die read()-Implementierung von ByteArrayInputStream wirft aber gar keine IOException (und warum sollte sie auch). Ich habe hier also toten Code, weil ich mich an gute und sinnvolle Grundsätze der Softwareentwicklung halte - und ich kann nicht 100% Testabdeckung erreichen, weil ich den code im catch-Block nicht testen kann.
20.10.2009
fenchurch 611 6
Das Beispiel stellt wohl nicht den gesamten Kontext dar, weshalb ich es schwierig finde zu beantworten. So wie ich den Auszug verstehe, testet er nur die Funktion einer Fremdklasse, da die Variable doc lokal ist.
Auszug aus der API: @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the configuration requested.

Wie gesagt, was ist der Sinn hinter dem Test? Bei offiziellen APIs kann man davon ausgehen, dass sie funktionieren.
LastFreeNickname 20.10.2009
Ok, ich habe mich vielleicht etwas zu kurz gefasst :-).

Nehmen wir mal an, ich täte etwas sinnvolles mit dem erzeugten Dokument (indem ich es z.B. aus einer Methode zurückliefere) und würde für den Code einen Unittest schreiben. newDocumentBuilder() wirft die Exception, ich kann aber nicht 100% Testabdeckung erreichen, weil es mir nicht gelingt, die Exception auszulösen und damit in den catch-Block zu kommen.
fenchurch 20.10.2009
Beim erneuten Lesen deines Kommentars geht fällt mir noch ein Missverständnis auf - mein Beispielcode ist nicht der Test, sonder der zu testende Code.
fenchurch 20.10.2009
So wie du das Problem schilderst, hätte ich persönlich kein Problem damit, weniger als 100% Abdeckung zu erreichen. Sonst müsstest du jede offizielle API durchtesten...
LastFreeNickname 20.10.2009
Naja, es ist rein psychologisch betrachtet schon unbefriedigend, wenn im Cobertura-Report so viel rot ist ;-) - aber mal im Ernst, in den anderen Antworten zur Testabdeckungsfrage, auch in deiner, war davon die Rede, dass 100% gut und wünschenswert ist (und da schließe ich mich auch an), aber manchmal weiß ich eben nicht, wie ich das hinbekommen kann. Auf dieses Problem wollte ich hier hinweisen und wenn irgendjemand eine gute Lösung dafür hat, konkret hier vor allem für Exceptions, die in der Praxis nie geworfen werden, wäre das natürlich super.
fenchurch 20.10.2009
1
Es ist aber auch kein Problem eine private Methode zu testen:

Folgende Methode soll getestet werden:
public class Controller {
private Date buildStartTime(final int intVal, final long longVal, final int intVal) {
...
}
}


JUnitTest:

Controller instance = new Controller();
Date result = null;
try {
Class clazz = Controller.class;
Method method = clazz.getDeclaredMethod("buildStartTime", new Class[]{Integer.TYPE, Long.TYPE, Integer.TYPE });
method.setAccessible(true);
result = (Date) method.invoke(instance, new Object[]{ 180, 60000L, 40});
} catch (Exception e) {
e.printStackTrace();
fail();
}
03.11.2009
stevetc 111 3
1
Anhand des folgenden Codeabschnitts wird klar, dass Code-Coverage überhaupt nichts über die Code-Qualität aussagt:

Man nehme diese Methode:

public int foo(int x, int y)
{
return x / y;
}


und denke sich nun einen einzigen Test aus wie z.B. "10 / 5". Dieser eine Testfall deckt bereits 100% ab, bringt aber gar nichts, denn übergebe mal 10 und 0...

=;O)
04.04.2012
CodingMan 168 5
LiRo 1,3k 1 9
0
Anweisungsüberdeckung ist glaube ich ein angemessener Kompromiss. Wenn man mehr Arbeit reinstecken möchte, strebt man Bedingungüberdeckung an. Zusätzlich sollte man Grenzwerttests für die one-off-Problematik erstellen.
25.05.2011
oopexpert 455 1 8
0
Prinzipell gilt auch beim testen ein ganz einfaches Prinzip:
So wenig wie möglich, soviel wie nötig!

Es ist sinnlos Klassen tot zu testen. (Tottestsn = 100%)
Wichtig ist, dass 80% der Klasse abgedeckt sind.
80/20 Prinzip (Paretoprinzip)

Du wirst sonst mit dem Testen vermutlich nicht mehr fertig werden.
Teste deine Programme so, wie sie in der praxis auch angewendet werden, aber schreibe keine sinnlosen Tests, den auch deren Ergebnisse werden dich zu keinem Ergebnis bringen.

Ps: Nur so als Anhang, wenn man Test-driven Development betreibt, hast du z.b. ja auch "nur" die Praxisfälle abgedeckt...
27.05.2011
Voi 216 3

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH