Je voudrais créer une suite de tests Junit en utilisant JUnit 4 où les noms des classes de test à inclure ne sont pas connus tant que la suite de tests n’est pas exécutée.
Dans JUnit 3, je pourrais le faire:
public final class MasterTester extends TestCase { /** * Used by junit to specify what TestCases to run. * * @return a suite containing what TestCases to run */ public static TestSuite suite() { TestSuite suite = new TestSuite(); for(Class klass : gatherTestClasses()) { suite.addTestSuite(klass); } return suite; } }
et laissez la méthode gatherTestClasses()
traiter de la détermination des classes de test à exécuter.
Dans JUnit 4, la documentation dit d’utiliser une annotation: @SuiteClasses({TestClass1.class, TestClass2.class...})
pour construire ma suite de tests. Il existe de nombreuses réponses SO montrant comment procéder. Malheureusement, les exemples que je vois ne semblent pas permettre de transmettre une liste générée dynamicment de TestClasses.
Cette réponse SO a suggéré que je devrais sous- BlockJUnit4ClassRunner
que je ne veux pas faire.
Les suites de tests spécifiées dynamicment semblent être quelque chose qui doit se trouver quelque part dans JUnit 4. Est-ce que quelqu’un sait où?
J’ai trouvé la suite Classpath très utile lorsqu’elle était utilisée avec une convention de nommage sur mes classes de test.
https://github.com/takari/takari-cpsuite
Voici un exemple:
import org.junit.extensions.cpsuite.ClasspathSuite; import org.junit.runner.RunWith; @RunWith(ClasspathSuite.class) @ClassnameFilters({".*UnitTest"}) public class MySuite { }
Je l’ai essayé avec JUnit 4.8 et ça marche:
@RunWith(AllTests.class) public class SomeTests { public static TestSuite suite() { TestSuite suite = new TestSuite(); suite.addTest(new JUnit4TestAdapter(Test1.class)); suite.addTest(new JUnit4TestAdapter(Test2.class)); return suite; } }
Pour créer une suite de tests dynamic, vous devez utiliser l’annotation @RunWith
. Il existe deux manières courantes de l’utiliser:
@RunWith(Suite.class)
Cela vous permet de spécifier quelles classes composent la suite de tests en question. Ceci est équivalent au style JUnit 3:
import junit.framework.TestSuite; import junit.framework.TestCase; public final class MasterTester extends TestCase { public static TestSuite suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(TestClass1.class); suite.addTestSuite(TestClass2.class); // etc... return suite; } }
La classe JUnit 4 équivalente sera:
import org.junit.runners.Suite; @RunWith(Suite.class) @SuiteClasses({TestClass1.class, TestClass2.class}) public final class MasterTester { }
@RunWith(AllTests.class)
Cela vous permet de spécifier dynamicment les tests qui composent la suite de tests. Si vos tests ne sont pas connus avant l’exécution, vous ne pouvez pas les spécifier dans les annotations. Vous pouvez utiliser cette construction à la place. Donc, si le code JUnit 3 est:
import junit.framework.TestCase; import junit.framework.TestSuite; import junit.framework.Test; public final class MasterTester extends TestCase { public static TestSuite suite() { TestSuite suite = new TestSuite(); for (Test test : findAllTestCasesRuntime()) { suite.addTest(test); } return suite; } }
Le code JUnit 4 équivalent sera:
import org.junit.runners.AllTests; import junit.framework.TestSuite; import junit.framework.Test; @RunWith(AllTests.class) public final class MasterTester { public static TestSuite suite() { TestSuite suite = new TestSuite(); for (Test test : findAllTestCasesRuntime()) { suite.addTest(test); } return suite; } }
Je ne suis pas sûr de ce que gatherTestClasses () fait, mais disons qu’il renvoie des tests lorsque le système d’exploitation est Linux et des tests différents lorsque le système d’exploitation est Windows. Vous pouvez répliquer cela dans JUnit 4.4 avec des hypothèses :
@Test public void onlyOnLinux() { assumeThat(getOS(), is(OperatingSystem.LINUX)); // rest of test } @Test public void onlyOnWindows() { assumeThat(getOS(), is(OperatingSystem.WINDOWS)); // rest of test } @Test public void anyOperatingSystem() { // just don't call assumeThat(..) }
L’implémentation de getOS()
et OperatingSystem
est votre code personnalisé.
Voici un exemple complet de la façon de l’implémenter. Il combine deux classes testCase et une suite.
ExampleInstrumentedTest:
import android.support.test.rule.ActivityTestRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class ExampleInstrumentedTest { @Rule public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class); @Test public void checkInputs() throws Exception { } }
ExampleInstrumentedTest2:
import android.support.test.rule.ActivityTestRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class ExampleInstrumentedTest2 { @Rule public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class); @Test public void checkInputs() throws Exception { } }
ExampleInstrumentedSuite:
import junit.framework.TestSuite; import org.junit.runner.RunWith; import org.junit.runners.AllTests; @RunWith(AllTests.class) public class ExampleInstrumentedSuite { public static TestSuite suite() { TestSuite suite = new TestSuite(); suite.addTest(new junit.framework.JUnit4TestAdapter(ExampleInstrumentedTest.class)); suite.addTest(new junit.framework.JUnit4TestAdapter(ExampleInstrumentedTest2.class)); return suite; } }
Notez que vous devez utiliser @RunWith(JUnit4.class)
au lieu de @RunWith(AndroidJUnit4.class)
par défaut dans la classe testCase