Как динамически создать набор тестов в JUnit 4? - PullRequest
51 голосов
/ 15 июля 2010

Я хотел бы создать набор тестов junit с использованием JUnit 4, в котором имена включаемых классов тестов неизвестны до тех пор, пока набор тестов не будет запущен.

В JUnit 3 я мог сделать это:

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;
  }
}

и позвольте методу gatherTestClasses() выяснить, какие тестовые классы запустить.

В JUnit 4 документация говорит об использовании аннотации: @SuiteClasses({TestClass1.class, TestClass2.class...}) для создания моего набора тестов. Есть многочисленные ответы SO , показывающие, как это сделать. К сожалению, примеры, которые я вижу, не позволяют передавать динамически генерируемый список TestClasses.

Этот SO ответ предполагает, что мне придется подкласс BlockJUnit4ClassRunner, что я не хочу делать.

Динамически определенные наборы тестов кажутся чем-то, что должно быть где-то в JUnit 4. Кто-нибудь знает где?

Ответы [ 5 ]

36 голосов
/ 13 августа 2012

Я пробовал это с помощью JUnit 4.8, и он работает:

@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;
     }
}
36 голосов
/ 13 сентября 2011

Для создания динамического набора тестов необходимо использовать аннотацию @RunWith. Есть два распространенных способа его использования:

@RunWith(Suite.class)

Это позволяет вам указать, какие классы составляют рассматриваемый набор тестов. Это эквивалентно стилю 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;
  }
}

Эквивалентный класс JUnit 4 будет:

import org.junit.runners.Suite;

@RunWith(Suite.class)
@SuiteClasses({TestClass1.class, TestClass2.class})
public final class MasterTester {

}

@RunWith(AllTests.class)

Это позволяет динамически указывать тесты, составляющие набор тестов. Если ваши тесты неизвестны до времени выполнения, вы не можете указать их в аннотациях. Вы можете использовать эту конструкцию вместо. Итак, если код JUnit 3:

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;
  }
}

Эквивалентный код JUnit 4 будет:

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;
  }
}
26 голосов
/ 20 июля 2010

Я считаю, что Classpath suite весьма полезен, когда он используется с соглашением об именах в моих тестовых классах.

https://github.com/takari/takari-cpsuite

Вот пример:

import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.runner.RunWith;

@RunWith(ClasspathSuite.class)
@ClassnameFilters({".*UnitTest"})
public class MySuite {
}
6 голосов
/ 15 июля 2010

Я не уверен, что делает collectTestClasses (), но, скажем, он возвращает некоторые тесты, когда ОС Linux, и другие тесты, когда ОС Windows. Вы можете повторить это в JUnit 4.4 с предположениями :

@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(..)
}

Реализация getOS() и OperatingSystem в качестве вашего пользовательского кода.

0 голосов
/ 23 февраля 2017

Вот полный пример того, как это реализовать.он объединяет два класса testCase и один набор.

  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;
        }
    }
    

Обратите внимание, что вы должны использовать @RunWith(JUnit4.class) вместопо умолчанию @RunWith(AndroidJUnit4.class) в классе testCase

...