JAVA: JUnitTest -, Prüf-Methode wirft zwei Ausnahmen
Ich Teste eine Methode wirft zwei verschiedenen Ausnahmen. Das ist mein header:
@Test (expected = A8InvalidInputException.class)
public void testGuessCharacter() throws A8InvalidInputException, A8AlreadyGuessedException
{
...
}
Der Körper hat zwei try/catch-Blöcke (eine Suche auf SO ergab eine post, die sagte, das ist, wie Sie testen, dass Ausnahmen geworfen werden), einen für jede Ausnahme. Es scheint mir, ich sollte brechen diese bis in zwei test-Methoden, vor allem, weil ich kann nur eine erwartet Attribut. Allerdings, wenn ich das Tue, ist die Methode soll testen A8InvalidInputException ist erforderlich, ein try/catch für A8AlreadyGuessedException, und die Methode soll testen A8AlreadyGuessedException ist erforderlich, ein try/catch für A8InvalidInputException. Ich bin mir nicht wirklich sicher, wie Sie Sie zu schreiben, diese zu testen. Dies ist die Methode, die ich bin versucht zu testen:
/**
* This method returns whether a specified character exists in the keyPhrase field
* @param guess a character being checked for in the keyPhrase field
* @return returns whether a specified character exists in the keyPhrase field
* @throws A8InvalidInputException if a non-valid character is passed as input to this method
* @throws A8AlreadyGuessedException if a valid character which has already been guessed is passed as input to this method
*/
public boolean guessCharacter(char guess) throws A8InvalidInputException, A8AlreadyGuessedException
{
if(isValidCharacter(guess))
{
guess = Character.toLowerCase(guess);
if(guessedCharacters.contains(guess) )
{
throw new A8AlreadyGuessedException("" + guess);
}
else
{
guessedCharacters.add(guess);
if(keyPhrase.contains("" + guess))
return true;
else
{
numberOfGuessesLeft--;
return false;
}
}
}
else
{
throw new A8InvalidInputException("" + guess);
}
}
- Die Methode ist zu lang sowieso.
- Dave, mein instructor zur Verfügung gestellt. Ich habe es nicht geschrieben. Abgesehen davon, dass ich dachte, 30-Linien wurde der von der Industrie akzeptierten max nach den Java-coding-guidelines/styleguides.
- "In der Industrie akzeptierte max?" Nie von so etwas gehört. Noch wichtiger ist, es hat eine high-genug zyklomatische Komplexität machen mich nervös: die Bedingungen sind zu tief geschachtelt, um ermöglichen eine einfache Argumentation, und es gibt verschachtelte, wo keine erforderlich ist. Duplizierte Logik, denn es gibt einen char, wenn alles andere erwartet einen string. Einfache Abflachung (etwa gist.github.com/davelnewton/258761cbf3143da4288c) löst dieses problem. Richtige refactoring macht testen so trivial, dass Sie fast lustig.
- Gut, die Prüfung ist für die Praxis, also es ist überhaupt nicht Komplex. Ich hatte einen Lehrer, der uns gelehrt, zu überprüfen von Eingaben VOR der übergabe als argument. Es wird verwirrend.
- Wo die Validierung von Daten geschieht, ist weitgehend unerheblich. Aber du bist falsch; die Methode ist an der oberen Grenze des zyklomatische Komplexität (10 ist eine typische Standard-max; ich Holen Sie sich nervös um ~5). Methoden sollten eine Sache zu tun, und tun es völlig. Diese Methode ist deutlich mehr als eine Sache, die Erhöhung der kognitiven Belastung ohne entsprechenden nutzen. Und es ist schwieriger zu testen als ein Ergebnis.
- Nun, wieder, es ist nicht mir. Es ist ein style-guide in mein text-Buch sagt, dass 30 Zeilen. Ich weiß nicht, wie übermäßig komplexe Methoden entweder, so Stimme ich mit Ihnen überein.
- Verwechseln Sie nicht die Linien mit mehr aussagekräftige Statistiken oder so offensichtliche Dinge wie "Form": eine lange Methode mit niedrigen CC ist leichter zu Grunde geht, als eine kurze Methode mit hohen CC. Ein Flachbild-Methode mit der gleichen CC wie eine verschachtelte Methode (z.B. erste Beispiel im gist) ist leichter zu Grunde geht.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kann eine Methode nur werfen eine Ausnahme, wenn es ran ist. Deshalb kann es nur eine erwartet zugeschrieben.
Sollten Sie die drei Testfälle: wenn die Methode wirft eine exception, wenn die Methode wirft die andere, und wenn die Methode nicht werfen-ohne Ausnahme-bei allen.
Setzen Sie keine try/catch-Anweisung in Ihrem
@Test
Methoden, nur erklären, dass Sie exceptions werfen.throws A8InvalidInputException, A8AlreadyGuessedException
im test-Methode header, aber jetzt sehe ich, du hast es geschafft. Also warum müssen Sie try/catch-Blöcke in den Körper?Fügen Sie einfach beide exceptions in der throws-Klausel:
Dann, wenn einer der Tests wirft die andere Ausnahme (die unerwartete eins), dann ist dein test wird automatisch scheitern.
Ja, teilen Sie diese in zwei unit-tests. Ein mit einer ungültigen Eingabe zum auslösen der
A8InvalidInputException
und anderen mit einer "erraten" - input zum Triggern desA8AlreadyGuessedException
.Berücksichtigen, dass das schreiben Ihre tests ein wenig einfacher, Sie zu brechen in zwei unterschiedliche Teile - Tests
isValidCharacter
und testenguessCharacter
getrennt.Davon ausgegangen, dass
isValidCharacter(guess)
wird scheitern, wenn Sie erhalten eine ungültige denke, ich denke, dass der RauswurfA8InvalidInputException
in dieser Methode wäre ideal.Dann alles, was Sie tun müssen, würde ist test , dass bestimmte Methode, um zu sehen, ob es wirft die exception auf den falschen Eingang.
Nächsten, Sie können ändern Sie Ihre Methode, um nur die Sorge um die happy-Pfad der
isValidCharacter
Methode, da Sie wenn Sie nicht zurückkehren, die boolean, den Sie geworfen haben, bilden die Ausnahme.Schließlich, Sie würden die einzige Sorge, die tests für
guessCharacter
um die Frage, ob oder nicht es wirftA8AlreadyGuessedException
.isValidCharacter
sollten wirft die Ausnahme, da es der einzige Teil des Codes zuständig für die Geltendmachung ungültige Eingabe. Nochmal, es geht um die Begrenzung der Höhe der Fläche, die Sie haben zu schlagen mit einem test - es lässt den test schreiben, Aufwand einfacher und produziert weniger zerbrechlich tests.