Testdatenerstellung: Permutationen
Veröffentlicht: Januar 30, 2011 Einsortiert unter: Java | Tags: dataprovider, Java, permutate, permutation, permutieren, testdaten Schreibe einen Kommentar »
Beim Testen mit DataProvidern kann es manchmal sinnvoll sein, dass man viele
verschieden Eingabeparameter testen möchte. Z.B. wenn man eine Methode tested,
die als einen Parameter eine Buffergröße hat, macht es Sinn dieselben Testdaten
mit verschiedenen Buffereinstellungen durchzuprobieren. Da die Ergebnisse
nicht von der Puffergröße abhängen kann man einfach alle Tests mit allen
Puffergrößen laufen lassen.
/** * <p> * Creates a permutation of the given 2-dimensional array * and the given 1-dimensional array. * </p> * <code> * <pre> * permutate(new Object[][] { {"foo", "bar"}, {"alice","bob"}}, * new Object[] {1,2}, * 1) * </pre> * </code> returns <code> * <pre> * new Object[][] { * {"foo", 1, "bar"}, * {"alice", 2,"bob"}, * {"foo", 1, "bar"}, * {"alice", 2, "bob"} * } * </pre> * </code> * * @param aData a 2-dimensional data object * @param aAdditionalColumn the additional column's data * @param aIndex the index where the additional column * is added to <code>aData</code> * @return the permutated array */ public Object[][] permutate( Object[][] aData, Object[] aAdditionalColumn, int aIndex) { final List<Object[]> result = new ArrayList<Object[]>(); for (Object additionalValue : aAdditionalColumn) { for (Object[] data : aData) { final Object[] newData = new Object[data.length + 1]; if (aIndex > 0) { System.arraycopy(data, 0, newData, 0, aIndex); } newData[aIndex] = additionalValue; if (aIndex + 1 < newData.length) { System.arraycopy(data, aIndex, newData, aIndex + 1, newData.length - aIndex - 1); } result.add(newData); } } return result.toArray(new Object[0][]); } Note: The code above is released to public domain.
TestNG: mit DataProvidern auf Exceptions testen
Veröffentlicht: November 28, 2010 Einsortiert unter: Java | Tags: dataprovider, exception, TestNG Schreibe einen Kommentar »
Das Testframework TestNG bietet DataProvider an, mit deren Hilfe es leicht möglich ist viele Kombinationen von Eingabeparametern zu überprüfen. Aber was macht man, wenn man bei bestimmten Eingaben eine Exception erwartet? Einen zweiten Test mit DataProvidern, so dass man einen Test für valide Eingaben und einen für invalide Eingaben hat? Oder sollte man die invaliden Eingaben lieber in separaten Testcases prüfen, damit man auch prüfen kann, dass die korrekte Exception fliegt?
Ich finde beide Lösungen etwas unübersichtlich. Aber zum Glück gibt es Abhilfe.
public String append(String s, String t) { if (s == null || t == null) throw new NullPointerException(); return s + t; } @DataProvider(name = "providerAppend") public Object[][] providerAppend() { return new Object[][] { { null, null, new NullPointerException() }, { "", null, new NullPointerException() }, { null, "", new NullPointerException() }, {"abc", "def", "abcdef" }, {"abc", "", "abc" }, {"", "def", "def" } }; } @Test(dataProvider = "providerAppend") public void testAppend(String s, String t, Object expected) { if (expected instanceof Exception) { try { append(s, t); Assert.fail("Expected an exception: " + expected.getClass()); } catch (Exception e) { Assert.assertEquals(e.getClass(), expected.getClass()); } } else { Assert.assertEquals(append(s,t), expected); } }
In obiger Lösung gehen wir einfach davon aus, dass es für den DataProvider egal ist, ob der Rückgabewert nun eine Wert oder eine Exception ist. Das handling wird dann in der Testmethode übernommen, und zwar dadurch, dass wir unterschiedliche Testimplementierungen wählen, je nachdem ob der erwartete Wert vom Typ Exception ist oder nicht. Wenn er vom Typ Exception ist, dann stellen wir sicher, dass eine Exception geworfen wird, und das die Klasse identisch mit der Erwartung ist. Manchmal kann es sinnvoll sein, denn Klassenvergleich gegen eine instanceof Prüfung zu ersetzen.
Caused by: java.rmi.RemoteException: -1
Veröffentlicht: Oktober 17, 2009 Einsortiert unter: Java | Tags: Java, RemoteException Schreibe einen Kommentar »
Caused by: java.rmi.RemoteException: -1
Dieser Fehler ist meist die Folge einer ArrayIndexOutOfBoundsException die während eines RMI calls auftrat. Irgendwo auf der Gegenseite ist die geflogen und wurde dann in eine RemoteException umgewandelt.
No enclosing instance of type InnerClassExample is accessible.
Veröffentlicht: Oktober 16, 2009 Einsortiert unter: Java | Tags: inner class, Java, No enclosing instance 4 Kommentare »
Die Fehlermeldung No enclosing instance of type InnerClassExample is accessible. Must qualify the allocation with an enclosing instance of type InnerClassExample (e.g. x.new A() where x is an instance of InnerClassExample). bekommt man immer dann, wenn man eine Klasse instantieren möchte, die als nicht statische innere Klasse definiert wurde. Wie zum Beispiel hier:
public class InnerClassExample
{
private static void aFunction()
{
InnerClass privateClass = new InnerClass();
}
private class InnerClass {}
}
Die Ursache ist, dass InnerClass nicht static definiert wurde. Wenn man InnerClass static macht funktionierts wie man das erwarten würde. Ich behaupte einfach mal, dass man in 95,3% der Fälle auch wirklich eine statische innere Klasse haben will, man kann das static also einfach dazuschreiben.
Und so siehts dann aus:
public class InnerClassExample
{
private static void aFunction()
{
InnerClass privateClass = new InnerClass();
}
private static class InnerClass {}
}
Hintergrund: Innere Klassen sind an ihre äußeren Klassen gebunden. So ist es möglich von der inneren Klasse auf Member der äußeren zuzugreifen. Damit das funktioniert muss klar sein von welcher Instanz der Member gelesen werden soll. Daher braucht es eine eins-zu-eins Beziehung zwischen äußerer und innerer Klasse. Diese Beziehung ist gegeben, wenn die innere Klasse in einer nicht statischen Methode erzeugt wird. Will man aber die innere Klasse aus einer statischen Methode, oder von einer anderen Klasse aus erzeugen, dann weiss Java nicht zu welcher Instanz der äußeren Klasse die Innere gehört.
Man hat also eigentlich mehrere Möglichkeiten:
1. Man macht die innere Klasse statisch. Dann kann man nicht mehr auf Member der äußeren Klasse zugreifen, aber man kann die Innere überall erzeugen.
2. Man zieht die innere Klasse in eine eigene Java Datei raus. Hat im Prinzip die gleichen Nachteile wie 1.
3. Man erzeugt eine extra Instanz der äußeren Klasse und benutzt deren new Operator. Das sieht dann so aus:
new InnerClassExample().new InnerClass();
Jep, das sieht etwas gewöhnungsbedürftig aus und ich hab das bislang noch nie in Code von erfahrenen Java-Programmierern gesehen.
4. Eine Variante von 3. ist, wenn man bereits eine Instanz von der äußeren Klasse hat, dann kann man die auch nehmen, z.B. so:
outclassInstance.new InnerClass();
Hab ich noch nie in der freien Natur gesehen. (Und das obwohl die Fehlermeldung genau diese Lösung vorschlägt.)
5. Man sieht ein, dass man eine innere Klasse nur innerhalb der äußeren Klasse benutzen sollte. Also macht man die Innere private (oder wenigstens protected) und baut seinen Code so um, dass er ohne die innere Klasse auskommt.
Hall Of Fame: Die schönsten Methoden-Signaturen
Veröffentlicht: Oktober 10, 2009 Einsortiert unter: Java Schreibe einen Kommentar »
Eine der schönsten Methoden-Signaturen, die ich bisher gesehen habe:
SomeException runCommand(Command aCommand, boolean aRunSilent) throws SomeException;
Mit Findbugs Bugs finden
Veröffentlicht: April 13, 2009 Einsortiert unter: Java | Tags: CodeAnalyzer, Findbugs, Java Schreibe einen Kommentar »Findbugs ist ein guter Helfer wenn es um das Aufspüren von Fehlern in Java geht. Im Folgenden möchte ich einige Features des Eclipse Findbugs-Plugins vorstellen.
Das Beispiel zeigt eine Null-Pointer Dereferenzierung in Zeile 14, die von Eclipse nicht erkannt wird.

FehlerDenEclipseNichtErkennt
Findbugs findet den Fehler:

Findbugs findet den Fehler und markiert ihn durch einen netten kleinen Käfer.
Aber Findbugs kann noch mehr. Z.B. kann er auch erkennen wenn man ineffizient programmiert, oder auch einfach unschöne Sachen macht.
Dabei sollte man allerdings immer beachten, dass diese Art der Codeanalyse nicht perfekt sein kann und alle Fehler erkennt. Das liegt nicht zuletzt daran, dass versucht wird false positives zu verhindern. In der Realität wird man eher auf false negatives stoßen, also fehlerhafte Situationen die Findbugs nicht erkennt. Aber das ist nicht wirklich schlimm, denn alles was Finbugs findet kann man als Gewinn verbuchen. Den Rest muss man halt weiterhin selbst suchen.
Die gezeigten Sachen sind zwar schon recht cool, aber Findbugs kann mehr. Und das ist richtig wuschig!
Nehmen wir mal folgende Funktion, wie sie eigentlich jeder schonmal geschrieben hat. Wir haben ein Argument und machen was damit. Aber wir sind faul und prüfen nicht, ob s gleich null ist. Die Folge ist, dass wir eine mögliche NullPointer-Exception haben.
Findbugs bemäkelt das nicht. Warum sollte er auch, schließlich wird der meiste Legacy-Code voll von sowas sein. Ausserdem kann Findbugs garnicht wissen, ob der Programmablauf vielleicht garantieren kann, dass niemals uppercaseA niemals mit null aufgerufen wird.
Das macht aber nichts, denn wir können Findbugs sagen, dass wir die Methode niemals mit null aufrufen möchten. Gemacht wird das mit Annotationen. Ich empfehle die JSR305 Annotationen (link kommt noch), weil bei diesen die Chance relativ hoch ist, dass sie in Java 7 offiziell unterstützt werden könnten. Um die JSR305 Annotationen mit dem Findbugs-Plugin für Eclipse nutzen zu können muss nur das jsr305.jar im Buildpath sein. Der Rest geht automagisch.
In obigem Beispiel könnten wir festschreiben, dass das Argument von uppercaseA nicht null sein darf. Dann kann Findbugs Stellen erkennen, die dagegen verstoßen. Dazu verwenden wir die @Nonnull Annotation.
Desweiteren könnten wir garantieren, dass uppercaseA niemals null zurückgibt, indem wir an den Rückgabewert die @Nonnull Annotation dranschreiben.
Weitere Annotation sind @CheckForNull Annotation, die besagt, dass die Methode / der Aufrufer das Argument auf null prüfen muss und die @Nullable Annotation die besagt, dass das Argument bzw. der Rückgabewert null sein können.
Das schöne an den Annotationen ist, dass man schon in der Signatur die Informationen hat, die sonst höchstens in der API stünden. Wenn man das konsequent durchzieht kann man so viele Fehler erkennen, bevor man das erstemal den Compiler startet.
Es gibt noch eine ganze Reihe weiterer Annotationen, die meistens selbsterklärend sind, z.B. @Nonnegative, @SuppressWarnings, @CheckReturnValue, …
Viele Links für Webentwickler
Veröffentlicht: Februar 24, 2009 Einsortiert unter: Java, Webentwicklung Schreibe einen Kommentar »Eine Seite die viele nützliche Seiten rund um Webentwicklung verlinkt: http://www.elementiks.com/web_resources.php. Und eine rund um Code Analyzer für Java: http://java-source.net/open-source/code-analyzers





