«1. Обзор

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

Проще говоря, чтобы указать собственный бегун, нам нужно использовать аннотацию @RunWith.

2. Подготовка

Давайте начнем с добавления стандартной зависимости JUnit в наш pom.xml:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>  
</dependency>

3. Реализация пользовательского запуска

В следующем примере мы покажем, как написать наш собственный Runner — и запустить его с помощью @RunWith.

JUnit Runner — это класс, который расширяет абстрактный класс JUnit Runner и отвечает за выполнение тестов JUnit, обычно с использованием отражения.

Здесь мы реализуем абстрактные методы класса Runner:

public class TestRunner extends Runner {

    private Class testClass;
    public TestRunner(Class testClass) {
        super();
        this.testClass = testClass;
    }

    @Override
    public Description getDescription() {
        return Description
          .createTestDescription(testClass, "My runner description");
    }

    @Override
    public void run(RunNotifier notifier) {
        System.out.println("running the tests from MyRunner: " + testClass);
        try {
            Object testObject = testClass.newInstance();
            for (Method method : testClass.getMethods()) {
                if (method.isAnnotationPresent(Test.class)) {
                    notifier.fireTestStarted(Description
                      .createTestDescription(testClass, method.getName()));
                    method.invoke(testObject);
                    notifier.fireTestFinished(Description
                      .createTestDescription(testClass, method.getName()));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Метод getDescription наследуется от Describable и возвращает описание, содержащее информацию, которая впоследствии экспортируется и может использоваться различными инструментами.

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

Мы определили конструктор, который принимает аргумент класса; это требование JUnit. Во время выполнения JUnit передаст целевой тестовый класс этому конструктору.

RunNotifier используется для запуска событий, содержащих информацию о ходе выполнения теста.

Давайте используем бегун в нашем тестовом классе:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

@RunWith(TestRunner.class)
public class CalculatorTest {
    Calculator calculator = new Calculator();

    @Test
    public void testAddition() {
        Syste.out.println("in testAddition");
        assertEquals("addition", 8, calculator.add(5, 3));
    }
}

Получим результат:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.baeldung.junit.CalculatorTest
running the tests from MyRunner: class com.baeldung.junit.CalculatorTest
in testAddition
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

4. Специализированные бегуны

Вместо того, чтобы расширять низкоуровневый класс бегунов, как мы делали в В последнем примере мы можем расширить один из специализированных подклассов Runner: ParentRunner или BlockJUnit4Runner.

Абстрактный класс ParentRunner запускает тесты в иерархическом порядке.

BlockJUnit4Runner — это конкретный класс, и если мы предпочитаем настраивать определенные методы, мы, вероятно, будем расширять этот класс.

Давайте посмотрим это на примере:

public class BlockingTestRunner extends BlockJUnit4ClassRunner {
    public BlockingTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected Statement methodInvoker(FrameworkMethod method, Object test) {
        System.out.println("invoking: " + method.getName());
        return super.methodInvoker(method, test);
    }
}

Аннотирование класса с помощью @RunWith(JUnit4.class) всегда будет вызывать исполняющую программу JUnit 4 по умолчанию в текущей версии JUnit; этот класс является псевдонимом текущего средства выполнения класса JUnit 4 по умолчанию:

@RunWith(JUnit4.class)
public class CalculatorTest {
    Calculator calculator = new Calculator();

    @Test
    public void testAddition() {
        assertEquals("addition", 8, calculator.add(5, 3));
    }
}

5. Заключение

Средства выполнения JUnit легко адаптируются и позволяют разработчику изменять процедуру выполнения теста и весь процесс тестирования.

Если мы хотим внести лишь незначительные изменения, неплохо было бы взглянуть на защищенные методы исполнителя BlockJUnit4Class.

Некоторые популярные сторонние реализации бегунов для использования включают SpringJUnit4ClassRunner, MockitoJUnitRunner, HierarchicalContextRunner, Cucumber Runner и многие другие.

Реализацию всех этих примеров и фрагментов кода можно найти в проекте GitHub — это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.