Как я могу создать тестовый набор в JUnit 4?
Я хотел бы создать набор тестов 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 где-то. Кто-нибудь знает, где?
Ответы
Ответ 1
Я обнаружил, что класс classpath весьма полезен при использовании с соглашением об именах в моих тестовых классах.
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 {
}
Ответ 2
Я пробовал это с помощью 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;
}
}
Ответ 3
Чтобы создать динамический набор тестов, вам нужно использовать аннотацию @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;
}
}
Ответ 4
Я не уверен, что делает команда gatherTestClasses(), но пусть он возвращает некоторые тесты, когда ОС - это Linux и разные тесты, когда ОС - это Windows. Вы можете воспроизвести это в JUnit 4.4 с помощью assumptions:
@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
является вашим пользовательским кодом.
Ответ 5
Вот полный пример того, как это реализовать. он объединяет два класса testCase и один набор.
-
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 {
}
}
-
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 {
}
}
-
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