J'essaie de préformer la configuration et le démontage pour un ensemble de tests d'intégration, en utilisant jUnit 4.4 pour exécuter les tests. Le démontage doit être exécuté de manière fiable. J'ai d'autres problèmes avec TestNG, donc je cherche à revenir sur jUnit. Quels hooks sont disponibles pour l'exécution avant l'exécution des tests et une fois tous les tests terminés?
Remarque: nous utilisons maven 2 pour notre build. J'ai essayé d'utiliser les phases pre-
& de post-integration-test
maven, mais si un test échoue, maven s'arrête et ne s'exécute pas post-integration-test
, ce qui n'aide pas.
java
testing
junit
integration-testing
sblundy
la source
la source
post-integration-test
si un test échoue. Voir aussi cette page wiki .Réponses:
Oui, il est possible d'exécuter de manière fiable des méthodes de configuration et de suppression avant et après les tests d'une suite de tests. Laissez-moi vous démontrer dans le code:
package com.test; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({Test1.class, Test2.class}) public class TestSuite { @BeforeClass public static void setUp() { System.out.println("setting up"); } @AfterClass public static void tearDown() { System.out.println("tearing down"); } }
Donc, votre
Test1
classe ressemblerait à quelque chose comme:package com.test; import org.junit.Test; public class Test1 { @Test public void test1() { System.out.println("test1"); } }
... et vous pouvez imaginer que cela
Test2
semble similaire. Si vous couriezTestSuite
, vous obtiendrez:Ainsi, vous pouvez voir que la configuration / la suppression ne s'exécutent qu'avant et après tous les tests, respectivement.
Le hic: cela ne fonctionne que si vous exécutez la suite de tests et que vous n'exécutez pas Test1 et Test2 en tant que tests JUnit individuels. Vous avez mentionné que vous utilisiez maven, et le plugin maven surefire aime exécuter des tests individuellement et ne fait pas partie d'une suite. Dans ce cas, je recommanderais de créer une superclasse que chaque classe de test étend. La superclasse contient alors les méthodes annotées @BeforeClass et @AfterClass. Bien que pas aussi propre que la méthode ci-dessus, je pense que cela fonctionnera pour vous.
En ce qui concerne le problème des tests ayant échoué, vous pouvez définir maven.test.error.ignore afin que la compilation continue en cas d'échec des tests. Ce n'est pas recommandé comme pratique continue, mais cela devrait vous permettre de fonctionner jusqu'à ce que tous vos tests réussissent. Pour plus de détails, consultez la documentation maven surefire .
la source
Un de mes collègues a suggéré ce qui suit: vous pouvez utiliser un RunListener personnalisé et implémenter la méthode testRunFinished (): http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html#testRunFinished(org. junit.runner.Result)
Pour enregistrer le RunListener, configurez simplement le plugin surefire comme suit: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html section "Utilisation d'écouteurs et de reporters personnalisés"
Cette configuration doit également être sélectionnée par le plugin de sécurité. Cette solution est excellente car vous n'avez pas besoin de spécifier des suites, des classes de test de recherche ou tout autre chose - elle permet à Maven de faire sa magie, en attendant que tous les tests soient terminés.
la source
Vous pouvez utiliser l' annotation @ClassRule dans JUnit 4.9+ comme je l'ai décrit dans une réponse à une autre question .
la source
En utilisant des annotations, vous pouvez faire quelque chose comme ceci:
import org.junit.*; import static org.junit.Assert.*; import java.util.*; class SomethingUnitTest { @BeforeClass public static void runBeforeClass() { } @AfterClass public static void runAfterClass() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testSomethingOrOther() { } }
la source
Ici, nous
la source
Quant à "Note: nous utilisons maven 2 pour notre build. J'ai essayé d'utiliser les phases de test pré et post-intégration de maven, mais, si un test échoue, maven s'arrête et n'exécute pas le test post-intégration , ce qui n’aide pas. "
vous pouvez essayer le plugin de sécurité à la place, je pense qu'il a la possibilité de s'assurer que le nettoyage se produit indépendamment de la configuration ou de l'état de l'étape intermédiaire
la source
A condition que tous vos tests puissent étendre une classe "technique" et soient dans le même package, vous pouvez faire une petite astuce:
public class AbstractTest { private static int nbTests = listClassesIn(<package>).size(); private static int curTest = 0; @BeforeClass public static void incCurTest() { curTest++; } @AfterClass public static void closeTestSuite() { if (curTest == nbTests) { /*cleaning*/ } } } public class Test1 extends AbstractTest { @Test public void check() {} } public class Test2 extends AbstractTest { @Test public void check() {} }
Sachez que cette solution présente de nombreux inconvénients:
Pour information: listClassesIn () => Comment trouver toutes les sous-classes d'une classe donnée en Java?
la source
Autant que je sache, il n'y a pas de mécanisme pour faire cela dans JUnit, mais vous pouvez essayer de sous-classer Suite et de remplacer la méthode run () par une version qui fournit des hooks.
la source
Étant donné que maven-surefire-plugin n'exécute pas la classe Suite en premier, mais traite les classes de suite et de test de la même manière, nous pouvons donc configurer le plugin comme ci-dessous pour activer uniquement les classes de suite et désactiver tous les tests. Suite exécutera tous les tests.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <includes> <include>**/*Suite.java</include> </includes> <excludes> <exclude>**/*Test.java</exclude> <exclude>**/*Tests.java</exclude> </excludes> </configuration> </plugin>
la source
La seule façon que je pense alors d'obtenir la fonctionnalité que vous voulez serait de faire quelque chose comme
import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("TestEverything"); //$JUnit-BEGIN$ suite.addTestSuite(TestOne.class); suite.addTestSuite(TestTwo.class); suite.addTestSuite(TestThree.class); //$JUnit-END$ } public static void main(String[] args) { AllTests test = new AllTests(); Test testCase = test.suite(); TestResult result = new TestResult(); setUp(); testCase.run(result); tearDown(); } public void setUp() {} public void tearDown() {} }
J'utilise quelque chose comme ça dans eclipse, donc je ne suis pas sûr à quel point il est portable en dehors de cet environnement
la source
Si vous ne voulez pas créer de suite et que vous devez lister toutes vos classes de test, vous pouvez utiliser la réflexion pour trouver le nombre de classes de test de manière dynamique et compter à rebours dans une classe de base @AfterClass pour faire le tearDown une seule fois:
public class BaseTestClass { private static int testClassToRun = 0; // Counting the classes to run so that we can do the tear down only once static { try { Field field = ClassLoader.class.getDeclaredField("classes"); field.setAccessible(true); @SuppressWarnings({ "unchecked", "rawtypes" }) Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader()); for (Class<?> clazz : classes) { if (clazz.getName().endsWith("Test")) { testClassToRun++; } } } catch (Exception ignore) { } } // Setup that needs to be done only once static { // one time set up } @AfterClass public static void baseTearDown() throws Exception { if (--testClassToRun == 0) { // one time clean up } } }
Si vous préférez utiliser @BeforeClass au lieu des blocs statiques, vous pouvez également utiliser un indicateur booléen pour effectuer le décompte des réflexions et tester la configuration une seule fois lors du premier appel. J'espère que cela aide quelqu'un, il m'a fallu un après-midi pour trouver un meilleur moyen que d'énumérer toutes les classes dans une suite.
Il ne vous reste plus qu'à étendre cette classe à toutes vos classes de test. Nous avions déjà une classe de base pour fournir des éléments communs pour tous nos tests, donc c'était la meilleure solution pour nous.
L'inspiration vient de cette réponse SO https://stackoverflow.com/a/37488620/5930242
Si vous ne voulez pas étendre cette classe partout, cette dernière réponse SO pourrait faire ce que vous voulez.
la source