web-dev-qa-db-fra.com

Comment créer dynamiquement une suite de tests dans JUnit 4?

J'aimerais créer une suite de tests Junit à l'aide de JUnit 4, dans laquelle les noms des classes de tests à inclure ne sont pas connus jusqu'à l'exécution de la suite de tests.

Dans JUnit 3, je pourrais faire ceci:

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() déterminer les 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 y a plusieurs SO réponses montrant comment faire cela. Malheureusement, les exemples que je vois ne semblent pas permettre de transmettre une liste de TestClasses générée dynamiquement.

Cette SO réponse m'a suggéré de sous-classer BlockJUnit4ClassRunner, ce que je ne veux pas faire.

Les suites de tests spécifiées dynamiquement semblent être quelque chose qui doit figurer dans JUnit 4 quelque part. Est-ce que quelqu'un sait où?

49
Tom Tresansky

J'ai trouvé la suite Classpath assez utile lorsqu'elle est utilisée avec une convention de dénomination 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 {
}
26
JavaRocky

J'ai essayé cela en utilisant JUnit 4.8 et cela fonctionne:

@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;
     }
}
35
Andrejs

Pour créer une suite de tests dynamiques, vous devez utiliser l'annotation @RunWith. Il y a deux façons 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 équivalente JUnit 4 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 dynamiquement 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 équivalent de JUnit 4 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;
  }
}
34
Danail Nachev

Je ne sais pas ce que cueillitTestClasses (), mais supposons qu'il renvoie des tests lorsque le système d'exploitation est Linux et différents tests lorsque le système d'exploitation est Windows. Vous pouvez répliquer cela dans JUnit 4.4 avec suppositions :

@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 étant votre code personnalisé.

6
Brad Cupit

Voici un exemple complet sur la façon de mettre en œuvre cela. il combine deux classes testCase et une suite.

  1. 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<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
    
        @Test
        public void checkInputs() throws Exception {
    
        }
    }
    
  2. 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<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
    
        @Test
        public void checkInputs() throws Exception {
    
        }
    }
    
  3. 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 testCase Class.

0
Maher Abuthraa