Перейти к основному содержимому

Программный запуск тестов JUnit из приложения Java

· 5 мин. чтения

1. Обзор

В этом руководстве мы покажем, как запускать тесты JUnit непосредственно из кода Java — есть сценарии, в которых эта опция пригодится.

Если вы новичок в JUnit или хотите перейти на JUnit 5, вы можете ознакомиться с некоторыми из многочисленных руководств по этой теме, которые у нас есть.

2. Зависимости Maven

Нам понадобится пара основных зависимостей для запуска тестов JUnit 4 и JUnit 5:

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>

// for JUnit 4
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

Последние версии JUnit 4, JUnit 5 и JUnit Platform Launcher можно найти на Maven Central.

3. Запуск тестов JUnit 4

3.1. Сценарий тестирования

Как для JUnit 4, так и для JUnit 5 мы создадим несколько тестовых классов-заполнителей, которых будет достаточно для демонстрации наших примеров:

public class FirstUnitTest {

@Test
public void whenThis_thenThat() {
assertTrue(true);
}

@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}

@Test
public void whenSomethingElse_thenSomethingElse() {
assertTrue(true);
}
}
public class SecondUnitTest {

@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}

@Test
public void whensomethingElse_thenSomethingElse() {
assertTrue(true);
}
}

При использовании JUnit 4 мы создаем тестовые классы, добавляя аннотацию @Test к каждому тестовому методу.

Мы также можем добавить другие полезные аннотации, такие как @Before или @After , но это не входит в задачи данного руководства.

3.2. Запуск одного тестового класса

Чтобы запустить тесты JUnit из кода Java, мы можем использовать класс JUnitCore (с добавлением класса TextListener , используемого для отображения вывода в System.out ):

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(FirstUnitTest.class);

В консоли мы увидим очень простое сообщение об успешных тестах:

Running one test class:
..
Time: 0.019
OK (2 tests)

3.3. Запуск нескольких тестовых классов

Если мы хотим указать несколько тестовых классов с помощью JUnit 4, мы можем использовать тот же код, что и для одного класса, и просто добавить дополнительные классы:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

Result result = junit.run(
FirstUnitTest.class,
SecondUnitTest.class);

resultReport(result);

Обратите внимание, что результат хранится в экземпляре класса JUnit Result , который мы распечатываем с помощью простого служебного метода:

public static void resultReport(Result result) {
System.out.println("Finished. Result: Failures: " +
result.getFailureCount() + ". Ignored: " +
result.getIgnoreCount() + ". Tests run: " +
result.getRunCount() + ". Time: " +
result.getRunTime() + "ms.");
}

3.4. Запуск набора тестов

Если нам нужно сгруппировать некоторые тестовые классы для их запуска, мы можем создать TestSuite . Это просто пустой класс, в котором мы указываем все классы с помощью аннотаций JUnit:

@RunWith(Suite.class)
@Suite.SuiteClasses({
FirstUnitTest.class,
SecondUnitTest.class
})
public class MyTestSuite {
}

Чтобы запустить эти тесты, мы снова будем использовать тот же код, что и раньше:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(MyTestSuite.class);
resultReport(result);

3.5. Выполнение повторных тестов

Одной из интересных особенностей JUnit является то, что мы можем повторять тесты, создавая экземпляры RepeatedTest . Это может быть очень полезно, когда мы тестируем случайные значения или проверяем производительность.

В следующем примере мы запустим тесты из MergeListsTest пять раз:

Test test = new JUnit4TestAdapter(FirstUnitTest.class);
RepeatedTest repeatedTest = new RepeatedTest(test, 5);

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

junit.run(repeatedTest);

Здесь мы используем JUnit4TestAdapter в качестве оболочки для нашего тестового класса.

Мы даже можем создавать наборы программно, применяя повторное тестирование:

TestSuite mySuite = new ActiveTestSuite();

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3));

junit.run(mySuite);

4. Запуск тестов JUnit 5

4.1. Сценарий тестирования

В JUnit 5 мы будем использовать те же тестовые классы, что и в предыдущей демонстрации — FirstUnitTest и SecondUnitTest , с некоторыми незначительными отличиями из-за другой версии JUnit framework, например, пакет для @Test и методы утверждения.

4.2. Запуск одного тестового класса

Чтобы запустить тесты JUnit 5 из кода Java, мы настроим экземпляр LauncherDiscoveryRequest . Он использует класс построителя, в котором мы должны установить селекторы пакетов и фильтры имен тестовых классов, чтобы получить все тестовые классы, которые мы хотим запустить.

Затем этот запрос связывается со средством запуска, и перед выполнением тестов мы также настраиваем план тестирования и прослушиватель выполнения.

Оба они предложат информацию о тестах, которые будут выполнены, и о результатах:

public class RunJUnit5TestsFromJava {
SummaryGeneratingListener listener = new SummaryGeneratingListener();

public void runOne() {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectClass(FirstUnitTest.class))
.build();
Launcher launcher = LauncherFactory.create();
TestPlan testPlan = launcher.discover(request);
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
}
// main method...
}

4.3. Запуск нескольких тестовых классов

Мы можем установить селекторы и фильтры для запроса на запуск нескольких тестовых классов.

Давайте посмотрим, как мы можем установить селекторы пакетов и фильтры имен тестовых классов, чтобы получить все тестовые классы, которые мы хотим запустить:

public void runAll() {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("com.foreach.junit5.runfromjava"))
.filters(includeClassNamePatterns(".*Test"))
.build();
Launcher launcher = LauncherFactory.create();
TestPlan testPlan = launcher.discover(request);
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
}

4.4. Тестовый вывод

В методе main() мы вызываем наш класс, а также используем прослушиватель для получения сведений о результате. На этот раз результат сохраняется как TestExecutionSummary .

Самый простой способ извлечь его информацию — просто напечатать в поток вывода консоли:

public static void main(String[] args) {
RunJUnit5TestsFromJava runner = new RunJUnit5TestsFromJava();
runner.runAll();

TestExecutionSummary summary = runner.listener.getSummary();
summary.printTo(new PrintWriter(System.out));
}

Это даст нам детали нашего тестового прогона:

Test run finished after 177 ms
[ 7 containers found ]
[ 0 containers skipped ]
[ 7 containers started ]
[ 0 containers aborted ]
[ 7 containers successful ]
[ 0 containers failed ]
[ 10 tests found ]
[ 0 tests skipped ]
[ 10 tests started ]
[ 0 tests aborted ]
[ 10 tests successful ]
[ 0 tests failed ]

5. Вывод

В этой статье мы показали, как программно запускать тесты JUnit из кода Java, охватывая JUnit 4, а также недавнюю версию JUnit 5 этой среды тестирования.

Как всегда, реализация показанных здесь примеров доступна на GitHub как для примеров JUnit 5 , так и для JUnit 4 .