Quelle est la différence entre l'échec et l'erreur dans JUnit?

93

J'exécute des tests JUnit sur une grande base de code, et je me suis rendu compte que parfois j'obtiens des "erreurs" tandis que d'autres fois j'obtiens des "échecs". Quelle est la différence?

froadie
la source

Réponses:

116

Ok, je viens de remarquer un motif et je pense l'avoir compris (corrigez-moi si je me trompe). Il me semble que les échecs surviennent lorsque vos cas de test échouent - c'est-à-dire que vos affirmations sont incorrectes. Les erreurs sont des erreurs inattendues qui se produisent lors de la tentative d'exécution du test - exceptions, etc.

froadie
la source
5
Cependant, si quelque chose s'étendant java.lang.AssertionErrorest levé, il sera affiché comme un échec de test au lieu d'une erreur de test. Vous devriez envisager d'accepter votre propre réponse car elle est correcte.
ponzao
Oui, c'est exactement la différence. Et d'un point de vue pragmatique, il n'y a «aucune différence» - en ce sens que si vous obtenez une erreur ou un échec, vous devez y remédier. Donc c'était probablement une erreur de compter les "échecs" et les "erreurs" séparément dans JUnit. JUnit 4 combine les deux (comme expliqué dans une réponse ci-dessous).
Jeff Grigg
Et si l'exception est attendue, vous devez annoter le @Testavec expected = SomeException.class.
Downhillski
@JeffGrigg il y a une différence pragmatique. Si un comportement est utilisé dans plusieurs cas de test, je ne peux toujours écrire qu'un seul cas de test qui affirme ce comportement, tout en lançant des exceptions d'exécution non interceptées, probables dans tout le reste. Cela signifie que le reste des cas de test testent autre chose même s'ils dépendent toujours de ce comportement particulier pour s'exécuter. Lorsque ce comportement est interrompu, un seul cas de test signalera un échec tandis que le reste signale une erreur, et à partir de là, je peux voir que j'ai exactement un bogue à corriger même si de nombreux cas de test n'ont pas réussi.
RonJRH
org.junit.Assert.assertEquals () en cas d'échec est considéré comme ERREUR par le rapport HTML JUnit4. Cela contredit votre déclaration (dont j'étais au courant jusqu'à présent). Pouvez-vous s'il vous plaît mettre plus de lumière là-dessus?
Krishnom
15

Si votre test lève une exception qui ne se propage pas dans le cadre d'assertion dans Junit, elle est signalée comme une erreur. Par exemple, un NullPointer ou une exception ClassNotFound signalera une erreur:

String s = null;
s.trim();

ou,

try {

    // your code
} catch(Exception e) {
    // log the exception
    throw new MyException(e);
}

Cela dit, les éléments suivants signaleront un échec:

Assert.fail("Failure here");

ou,

Assert.assertEquals(1, 2);

ou même:

throw new AssertionException(e);

Cela dépend de la version de Junit que vous utilisez. Junit 4- fera la distinction entre un échec et une erreur, mais Junit 4 le simplifie comme des échecs uniquement.

Le lien suivant fournit des entrées plus intéressantes:

http://www.devx.com/Java/Article/31983/1763/page/2

Neel
la source
Ce n'est pas exact. La distinction entre un échec de test et une erreur de test n'a pas disparu dans JUnit 4. Je viens de le tester. L'article lié était trompeur. Il disait que "JUnit 4 simplifie les choses en n'utilisant que les échecs" mais il devrait souligner que JUnit 4 transforme java.lang.AssertionError en échecs de test afin que vous n'ayez pas à utiliser junit.framework.AssertionFailedError. L'avantage est que vous pouvez commencer à écrire des assertions de test dans le code de production sans que le projet soit lié à JUnit. La distinction entre l'erreur de test et l'échec du test est également extrêmement utile et constituerait un pas en arrière si elle était supprimée.
RonJRH
RonJRH, êtes-vous capable de voir les erreurs dans votre rapport junit par défaut?
Neel
Oui Neel. J'ai juste essayé. Je ne suis pas sûr de l'étique de la liaison de l'image ici, mais cela montre le résultat de mon test: imagebucket.net/abpxucddkvn1/Capture.PNG
RonJRH
6

Extrait de "Test unitaire pragmatique dans Java 8 avec JUnit":

Les assertions (ou assertions) dans JUnit sont des appels de méthode statiques que vous déposez dans vos tests. Chaque assertion est l'occasion de vérifier qu'une condition est vraie. Si une condition affirmée n'est pas vraie, le test s'arrête là et JUnit signale un échec du test.

(Il est également possible que lorsque JUnit exécute votre test, une exception soit levée et non interceptée. Dans ce cas, JUnit signale une erreur de test.)

Matias Elorriaga
la source
5

Le test ci-dessous explique la différence entre l' erreur de test et l'échec du test .

J'ai commenté la ligne qui jette une erreur de test et un échec de test.

    @Test
    public void testErrorVsTestFailure() {

        final String sampleString = null;

        assertEquals('j', sampleString.charAt(0) );
        //above line throws test error as you are trying to access charAt() method on null reference

        assertEquals(sampleString, "jacob");
        //above line throws Test failure as the actual value-a null , is not equal to expected value-string "jacob"
        }

Ainsi, Junit affiche une erreur de test chaque fois que vous obtenez une exception et un échec de test lorsque la valeur de résultat attendue ne correspond pas à votre valeur réelle

Deen John
la source
2

Classe source: JUnitReportReporter.java

public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String defaultOutputDirectory) {
//......

            for (ITestResult tr : (Set) entry.getValue()) {
                TestTag testTag = new TestTag();

                boolean isSuccess = tr.getStatus() == 1;
                if (!(isSuccess)) {
                    if (tr.getThrowable() instanceof AssertionError)
                        ++errors;
                    else {
                        ++failures;
                    }
                }
}

Comme vous pouvez le voir ci-dessous dans la méthode ci-dessus

tr.getThrowable () instanceof AssertionError

Le nombre d'erreurs est augmenté lorsqu'il s'agit d'une instance d'AssertionError, sinon (tout Throwable) est compté comme des échecs.

Roushan
la source
1

Vous avez raison de dire que les échecs proviennent des AssertionErrors levés par les méthodes d'assertion JUnit, ou en lançant une AssertionError, ou en lançant une exception que vous avez déclarée dans votre @Testannotation, et les erreurs proviennent d'autres exceptions inattendues. Mais il y a une distinction importante entre eux:

Un échec signifie que votre test s'est déroulé correctement et a identifié un défaut dans votre code.

Une erreur peut signifier un bogue dans votre code, mais que vous n'avez même pas testé. Cela pourrait également signifier que le bogue est dans le test lui-même.

En bref, un échec signifie que vous devez réécrire le code qui est testé. Une erreur signifie que c'est peut-être le test unitaire que vous devez réécrire. Cela peut signifier cela même si l'échec était dans votre code, par exemple a NullPointerException, parce que vous avez détecté une faille que vous n'avez même pas testée, il peut donc être judicieux de la tester.

MiguelMunoz
la source
0

Ironie du sort, JUnit et d' autres cadres liés aux tests (testng, hamcrest) fournissent assert opérations qui vérifient l' état et si elle échoue alors « sous le capot » un java.lang.AssertionError est jetés, qui s'étend BTW java.lang.Error.

Mais cela ne contredit nullement les réponses ci-dessus qui sont bien entendu pleinement valables. Donc, pour marquer un flux de test spécifique comme un échec, on peut lancer AssertionError, mais je ne suis pas sûr qu'il soit vraiment documenté dans les manuels correspondants, car il est plus approprié d'utiliser l'API fail () dédiée. Les autres types de Throwable seront considérés comme des erreurs et non comme des échecs.

agolubev81
la source
0

Fondamentalement, les échecs font référence à des assertions non satisfaites tandis que les erreurs sont dues à une exécution anormale des tests . et je pense que chaque IDE a des icônes symboliques avec des couleurs différentes pour réussir , échouer et avec des tests d' erreur .

Pour plus d'informations, vérifiez ceci .

Soufiane Roui
la source