2010-10-27 1 views
46

In der JUnit4-Bibliothek gibt es eine fail()-Methode. Ich mag es, aber einen Mangel an pass() Methode, die nicht in der Bibliothek vorhanden ist. Wieso ist es so?JUnit4 fail() ist hier, aber wo ist pass()?

Ich habe herausgefunden, dass ich stattdessen assertTrue(true) verwenden kann, aber immer noch unlogisch aussieht.

@Test 
public void testSetterForeignWord(){ 
    try { 
    card.setForeignWord(""); 
    fail(); 
    } catch (IncorrectArgumentForSetter ex){ 
    } 

// assertTrue(true); 
} 
+7

Verwenden Sie einfach Return-Anweisung - in den meisten Fällen wird dies als pass() übergeben. – topchef

+0

@topchef dieser einzelne Kommentar traf den Hammer auf den Kopf, während alle anderen darüber diskutieren, was akzeptabel ist und was nicht. –

+0

Einige Testsysteme (perl Test :: Simple) zählen bestandene und fehlgeschlagene Assertions. Junit zählt jedoch die Anzahl der _test-Methoden, die bestanden und nicht bestanden haben. Daher hat Junit nicht den gleichen Nutzen für eine "Pass" -Methode. –

Antwort

51

Solange der Test keine Ausnahme werfen, es geht, es sei denn, Ihr @Test Annotation eine erwartete Ausnahme angibt. Ich nehme an, eine pass() könnte eine spezielle Ausnahme werfen, die JUnit immer als Weitergabe interpretiert, um den Test kurzzuschließen, aber das würde gegen das übliche Design von Tests gehen (dh Erfolg annehmen und nur fehlschlagen, wenn eine Assertion fehlschlägt) und, wenn Leute kam die Idee, dass es vorzuziehen war, pass() zu verwenden, würde es eine große Anzahl von bestandenen Tests erheblich verlangsamen (aufgrund des Overheads der Erstellung von Ausnahmen). Scheitern Tests sollten nicht die Norm sein, so ist es keine große Sache, wenn sie diesen Overhead haben.

Beachten Sie, dass Ihr Beispiel wie folgt neu geschrieben werden:

@Test(expected=IncorrectArgumentForSetter.class) 
public void testSetterForeignWord("") throws Exception { 
    card.setForeignWord(""); 
} 

Außerdem sollten Sie die Verwendung von Standard-Java-Ausnahmen begünstigen. Ihr IncorrectArgumentForSetter sollte wahrscheinlich ein IllegalArgumentException sein.

+4

Die Methoden fail() und assertX() werfen in Wirklichkeit nur einen AssertionError, was dazu führt, dass die Testmethode unsauber beendet wird. Deshalb gibt eine erfolgreiche Rückkehr den Erfolg an ... –

+0

-1 - pass() -Methode tut nichts - es beendet den Test sofort ohne Ausnahmen. In den meisten Fällen entspricht dies einer Rückgabeanweisung (mit Ausnahme erwarteter Ausnahmen, Timeouts usw.). – topchef

+1

@grigory: Sie haben Recht, dass eine Methode 'pass()' nicht einfach nichts tun kann, damit ein Test nach dem Aufruf nicht fehlschlagen kann. Also habe ich diesen Satz entfernt. – ColinD

2

Die Pass-Methode ist nicht erforderlich. Wenn keine AssertionFailedException aus dem Testcode ausgelöst wird, wird der Unit-Test-Case bestanden.

Die fail() -Methode löst tatsächlich eine AssertionFailedException aus, um die testCase fehlzuschlagen, wenn die Kontrolle an diesem Punkt eintrifft.

+0

Ich denke, es ist tatsächlich ein junit.framework.AssertionFailedError. – Kyle

+0

Was ist mit den Fehlern Fällen. sag iam bekomme Element nicht sichtbar Ausnahme von webdriver.Should ich Ausnahme und zurückkommen. – sasikumar

50

Rufen Sie an return Anweisung immer wenn Ihr Test abgeschlossen ist und bestanden.

+1

+1 muss die richtige Antwort sein (in den meisten Fällen mit Ausnahme der erwarteten, Timeouts, etc.) – topchef

3

Ich denke, diese Frage braucht eine aktualisierte Antwort, da die meisten Antworten hier ziemlich veraltet sind.

Zum einen auf die Frage des OP:

Ich denke, es ist ziemlich gut angenommen, dass die „erwartete excepetion“ -Konzept in JUnit Einführung war ein schlechter Schachzug, da diese Ausnahme überall angehoben werden könnte, und es wird den Test bestehen. Es funktioniert, wenn Sie sehr domänenspezifische Exceptions werfen (und behaupten), aber ich werfe nur diese Art von Exceptions, wenn ich an Code arbeite, der absolut einwandfrei sein muss, - am meisten APIS wird einfach die eingebauten Ausnahmen wie IllegalArgumentException werfen oder IllegalStateException. Wenn zwei Aufrufe Ihre Erzeugung könnte potentally diese Ausnahmen werfen, dann wird die @ExpectedException Annotation Ihren Test grün-bar, auch wenn es die falsche Linie ist, die die Ausnahme auslöst!

Für diese Situation ich eine Klasse geschrieben habe, die ich bin sicher, dass viele andere hier geschrieben haben, das ist ein assertThrows Methode:

public class Exceptions { 
    private Exceptions(){} 

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){ 
     try{ 
      actionThatShouldThrow.run(); 
      fail("expected action to throw " + expectedException.getSimpleName() + " but it did not."); 
     } 
     catch(Exception e){ 
      if (! expectedException.isInstance(e)) { 
       throw e; 
      } 
     } 
    } 
} 

diese Methode einfach zurück, wenn die Ausnahme ausgelöst wird, so dass Sie tun weitere Aussagen/Verifizierungen in Ihrem Test

mit Java 8 Syntax sieht Ihr Test wirklich gut aus.Im Folgenden finden Sie eine der einfacheren Tests auf unserem Modell, das die Methode verwendet:

@Test 
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() { 
    //setup 
    AxisRange range = new AxisRange(0,100); 

    //act 
    Runnable act =() -> range.setLowerBound(200); 

    //assert 
    assertThrows(IllegalArgumentException.class, act); 
} 

diese Tests ein wenig wackelig sind, weil die „handeln“ Schritt eine Aktion nicht wirklich durchführen, aber ich denke, dass die Bedeutung noch recht ist klar.

Es gibt auch eine winzige kleine Bibliothek namens catch-exception, die die Mockito-Syntax verwendet, um zu überprüfen, ob Ausnahmen ausgelöst werden. Es sieht hübsch aus, aber ich bin kein Fan von dynamischen Proxies. Das heißt, es Syntax ist so glatt bleibt es verlockend:

// given: an empty list 
List myList = new ArrayList(); 

// when: we try to get the first element of the list 
// then: catch the exception if any is thrown 
catchException(myList).get(1); 

// then: we expect an IndexOutOfBoundsException 
assert caughtException() instanceof IndexOutOfBoundsException; 

schließlich für die Situation, die ich in lief auf diesen Thread zu bekommen, gibt es eine Möglichkeit, um ignorieren-Tests, wenn einige conidition erfüllt ist.

Momentan arbeite ich daran, einige DLLs über eine java native-library-loading-library namens JNA aufzurufen, aber unser Build-Server ist in ubuntu. Ich möchte versuchen, diese Art der Entwicklung mit JUnit-Tests voranzutreiben - auch wenn sie an dieser Stelle noch weit von "Einheiten" entfernt sind. Ich möchte den Test ausführen, wenn ich auf einem lokalen Computer bin, aber den Test ignorieren, wenn wir auf Ubuntu sind. JUnit 4 hat hierfür eine Rückstellung haben, die so genannte Assume:

@Test 
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException { 
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true. 
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI()); 
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup 
    URL url = DLLTestFixture.class.getResource("USERDLL.dll"); 
    String path = url.toURI().getPath(); 
    path = path.substring(0, path.lastIndexOf("/")); 

    //act 
    NativeLibrary.addSearchPath("USERDLL", path); 
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class); 

    //assert 
    assertThat(dll).isNotNull(); 
} 
1

Ich denke, dass diese Frage ergibt sich aus einem kleinen Missverständnis des Testausführungsprozess ist. In JUnit (und anderen Test-Tools) werden die Ergebnisse pro Methode und nicht pro Asser-Aufruf gezählt. Es gibt keinen Zähler, der verfolgt, wie viele bestanden/nicht bestanden assertX ausgeführt wurde.

JUnit führt jede Testmethode einzeln aus. Wenn die Methode erfolgreich zurückkehrt, wird der Test als "bestanden" registriert. Wenn eine Ausnahme auftritt, wird der Test als "fehlgeschlagen" registriert. Im letzteren Fall sind zwei Unterfälle möglich: 1) eine JUnit-Assertionsausnahme, 2) jede andere Art von Ausnahmen. Der Status wird im ersten Fall "fehlgeschlagen" und im zweiten Fall "Fehler" sein.

In der Klasse Assert stehen viele Kurzschreibmethoden zum Auslösen von Assertionsausnahmen zur Verfügung. Mit anderen Worten, Assert ist eine Abstraktionsschicht über JUnit-Ausnahmen.

Zum Beispiel ist dies der Quellcode assertEquals auf GitHub:

/** 
* Asserts that two Strings are equal. 
*/ 
static public void assertEquals(String message, String expected, String actual) { 
    if (expected == null && actual == null) { 
     return; 
    } 
    if (expected != null && expected.equals(actual)) { 
     return; 
    } 
    String cleanMessage = message == null ? "" : message; 
    throw new ComparisonFailure(cleanMessage, expected, actual); 
} 

Wie Sie sehen können, im Falle der Gleichheit nichts passiert, sonst wird ein excepion geworfen werden. So

:

assertEqual("Oh!", "Some string", "Another string!"); 

einfach wirft eine ComparisonFailure Ausnahme, die von JUnit gefangen werden, und

assertEqual("Oh?", "Same string", "Same string"); 

tut nichts.

In der Summe würde etwas wie pass() keinen Sinn ergeben, weil es nichts getan hat.

0

Ich suchte auch nach pass Methode für JUnit, so dass ich einige Tests kurzschließen konnte, die in einigen Szenarien nicht anwendbar waren (es gibt Integrationstests, anstatt reine Komponententests). So schlimm ist es nicht.

Glücklicherweise gibt es eine Möglichkeit, einen Test bedingt ignoriert zu haben, die besser passt eigentlich auch in meinem Fall mit assumeTrue Methode:

Assume.assumeTrue (isTestApplicable);

Also hier wird der Test nur ausgeführt, wenn isTestApplicable wahr ist, sonst Test wird ignoriert.