JUnit confusion: utilisez 'extends TestCase' ou '@Test'?


J'ai trouvé l'utilisation correcte (ou du moins la documentation) de JUnit très déroutante. Cette question sert à la fois de référence future et de vraie question.

Si j'ai bien compris, il existe deux approches principales pour créer et exécuter un test JUnit:

Approche A (JUnit 3-style): créez une classe qui étend TestCase et démarrez les méthodes de test avec le mot test. Lors de l'exécution de la classe en tant que test JUnit (dans Eclipse), toutes les méthodes démarrent avec le mot test sont automatiquement exécutées.

import junit.framework.TestCase;

public class DummyTestA extends TestCase {

    public void testSum() {
        int a = 5;
        int b = 10;
        int result = a + b;
        assertEquals(15, result);
    }
}

Approche B (JUnit 4-style): crée une classe 'normale' et ajoute une annotation @Test à la méthode. Notez que vous n'avez PAS besoin de démarrer la méthode avec le mot test.

import org.junit.*;
import static org.junit.Assert.*;

public class DummyTestB {

    @Test
    public void Sum() {
        int a = 5;
        int b = 10;
        int result = a + b;
        assertEquals(15, result);
    }
}

Mélanger les deux ne semble pas être une bonne idée, voir par exemple cette question stackoverflow:

Maintenant, mes questions:

  1. Quelle est l'approche préférée, ou quand utiliseriez-vous une au lieu de la les autres?
  2. L'approche B permet de tester les exceptions en étendant l'annotation @Test comme dans @Test(expected = ArithmeticException.class). Mais comment testez-vous les exceptions lors de l'utilisation de l'approche A?
  3. Lorsque vous utilisez l'approche A, vous pouvez regrouper un certain nombre de classes de test dans une suite de tests comme ceci:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class);

    Mais cela ne peut pas être utilisé avec l'approche B (puisque chaque classe de test devrait sous-classe TestCase). Quelle est la bonne façon de regrouper les tests pour l'approche B?

Edit: J'ai ajouté les versions JUnit aux deux approches

Author: Community, 2010-04-14

5 answers

La distinction est plutôt facile:

  • l'extension de TestCase est la façon dont les tests unitaires ont été écrits dans JUnit 3 (bien sûr, il est toujours pris en charge dans JUnit 4)
  • l'utilisation de l'annotation @Test est la voie introduite par JUnit 4

Généralement, vous devez choisir le chemin d'annotation, sauf si la compatibilité avec JUnit 3 (et/ou une version Java antérieure à Java 5) est nécessaire. La nouvelle méthode présente plusieurs avantages:

À testez les exceptions attendues dans un JUnit 3 TestCase vous devrez rendre le texte explicite.

public void testMyException() {
  try {
    objectUnderTest.myMethod(EVIL_ARGUMENT);
    fail("myMethod did not throw an Exception!");
  } catch (MyException e) {
    // ok!
    // check for properties of exception here, if desired
  }
}

JUnit 5 a introduit un autre changement d'API, mais utilise toujours des annotations. La nouvelle annotation @Test est org.junit.jupiter.api.Test (le" vieux " JUnit 4 était org.junit.Test), mais il fonctionne à peu près de la même manière que le JUnit 4.

 124
Author: Joachim Sauer, 2019-10-22 10:09:11

J'ai une préférence pour JUnit 4 (approche d'annotation) car je la trouve plus flexible.

Si vous voulez construire une suite de tests dans JUnit 4, vous devez créer une classe regroupant tous les tests comme ceci:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;


@RunWith(Suite.class)
@SuiteClasses({
    Test1.class,
    Test2.class,
    Test3.class,
    Test4.class
})public class TestSuite
{
 /* empty class */
}
 25
Author: Grimmy, 2010-04-14 08:21:45

Il y a une partie sans réponse à votre question, et c'est "Quelle est la bonne façon de regrouper les tests pour l'approche B?"

La réponse officielle est que vous annotez une classe avec un @RunWith(Suite.classe), puis utilisez la @ Suite.Annotation SuiteClasses pour lister les classes. C'est ainsi que les développeurs JUnit le font (liste manuelle de chaque classe d'une suite). À bien des égards, cette approche est une amélioration, en ce sens qu'il est trivial et intuitif d'ajouter des comportements avant et après suite (juste ajoutez une méthode @BeforeClass et @AfterClass à la classe annotée avec @RunWith-beaucoup mieux que l'ancien TestFixture).

Cependant, il a un pas en arrière, en ce sens que les annotations ne vous permettent pas de créer dynamiquement la liste des classes, et contourner ce problème devient un peu moche. Vous devez sous-classer la classe Suite et créer dynamiquement le tableau de classes dans la sous-classe et le transmettre au constructeur Suite, mais il s'agit d'une solution incomplète dans cet autre les sous-classes de la suite (telles que les catégories) ne fonctionnent pas avec elle et ne prennent essentiellement pas en charge la collection de classes de test dynamique.

 15
Author: Yishai, 2010-04-14 13:47:43

Vous devez utiliser JUnit 4. C'est mieux.

Beaucoup de frameworks ont commencé à déprécier le support JUnit 3.8.

Ceci provient de la documentation de référence Spring 3.0:

[Avertissement] Classe JUnit 3.8 héritée la hiérarchie est obsolète

En général, vous devriez toujours essayer d'utiliser la dernière version stable d'un cadre, lorsque vous commencez quelque chose de nouveau.

 4
Author: Espen, 2013-10-31 01:52:15
  1. L'approche "préférée"serait d'utiliser des annotations qui ont été introduites depuis le 4 juin. Ils facilitent beaucoup de choses (voir votre deuxième question)

  2. Vous pouvez utiliser un simple bloc try/catch pour que:


public void testForException() {
    try {
        Integer.parseInt("just a string");
        fail("Exception should have been thrown");
    } catch (final Exception e) {
        // expected
    }
}
 1
Author: black666, 2010-04-14 08:39:09