«1. Обзор

Давайте представим, что у нас есть тест для некоторого кода, который зависит от операционной системы и должен выполняться только в том случае, если наша тестовая машина работает под управлением Linux. Если он работает на любой другой ОС, мы хотим, чтобы тест не провалился, а игнорировался во время выполнения.

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

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

2. Класс Assume

Этот класс предоставляет набор методов для поддержки выполнения условного теста на основе определенных условий. Наш тест будет работать только при соблюдении всех этих условий. Если нет, JUnit просто пропустит его выполнение и пометит его как пройденный в отчете о тестировании. Последнее является основным отличием от класса Assert, в котором условие сбоя приводит к тому, что тест завершается как сбой.

Важно отметить, что поведение, которое мы описали для класса Assume, является эксклюзивным для исполнителя JUnit по умолчанию. С пользовательскими бегунками все может быть по-другому.

Наконец, так же, как и с Assert, мы можем вызывать методы Assume либо в аннотированных методах @Before или @BeforeClass, либо внутри самого метода @Test.

Давайте теперь пройдемся по наиболее полезным методам класса Assume, показав несколько примеров. Для всех следующих примеров предположим, что getOsName() возвращает Linux.

2.1. Использование acceptThat

Метод acceptThat() проверяет, что состояние — в данном случае getOsName() — удовлетворяет условиям переданного сопоставителя:

@Test
public void whenAssumeThatAndOSIsLinux_thenRunTest() {
    assumeThat(getOsName(), is("Linux"));

    assertEquals("run", "RUN".toLowerCase());
}

В этом примере мы проверяли, соответствует ли getOsName () равно Linux. Поскольку getOsName() возвращает Linux, тест будет запущен. Обратите внимание, что здесь мы используем метод сопоставителя Hamcrest is(T) в качестве сопоставителя.

2.2. Использование acceptTrue

Точно так же мы можем использовать метод acceptTrue() для указания логического выражения, которое должно быть истинным, чтобы тест запустился. Если он оценивается как false, тест будет проигнорирован:

private boolean isExpectedOS(String osName) {
    return "Linux".equals(osName);
}

@Test 
public void whenAssumeTrueAndOSIsLinux_thenRunTest() {
    assumeTrue(isExpectedOS(getOsName()));
 
    assertEquals("run", "RUN".toLowerCase());
}

В этом случае isExpectedOs() возвращает true. Следовательно, условия для запуска теста выполнены, и тест будет запущен.

2.3. Использование acceptFalse

Наконец, мы можем использовать противоположный метод acceptFalse() для указания логического выражения, которое должно быть ложным для запуска теста. Если оно оценивается как true, тест будет проигнорирован:

@Test
public void whenAssumeFalseAndOSIsLinux_thenIgnore() {
    assumeFalse(isExpectedOS(getOsName()));

    assertEquals("run", "RUN".toLowerCase());
}

В этом случае, поскольку isExpectedOs() также возвращает true, условия для запуска теста не выполнены, и тест будет проигнорирован.

2.4. Использование acceptNotNull

Когда мы хотим проигнорировать тест, если какое-то выражение имеет значение null, мы можем использовать метод acceptNotNull():

@Test
public void whenAssumeNotNullAndNotNullOSVersion_thenRun() {
    assumeNotNull(getOsName());

    assertEquals("run", "RUN".toLowerCase());
}

Так как getOsName() возвращает ненулевое значение, условие для теста to run был удовлетворен, и тест будет запущен.

2.5. Использование acceptNoException

Наконец, мы можем захотеть проигнорировать тест, если возникнет исключение. Для этой цели мы можем использовать acceptNoException():

@Test
public void whenAssumeNoExceptionAndExceptionThrown_thenIgnore() {
    assertEquals("everything ok", "EVERYTHING OK".toLowerCase());
    String t=null;
    try {
        t.charAt(0);
    } catch(NullPointerException npe){
        assumeNoException(npe);
    }
    assertEquals("run", "RUN".toLowerCase());
}

В этом примере, поскольку t равно null, генерируется исключение NullPointerException, поэтому условия для запуска теста не выполнены, и тест будет проигнорирован. .

3. Куда следует поместить вызов acceptXXX?

Важно отметить, что поведение методов acceptXXX зависит от того, где мы поместили их в наши тесты.

Давайте немного изменим наш пример, чтобы вызов assertEquals() выполнялся первым. Кроме того, давайте сделаем так, чтобы assertEquals() не выполнялся:

@Test
public void whenAssumeFalseAndOSIsLinux_thenIgnore() {
    assertEquals("run", "RUN");
    assumeFalse(isExpectedOS(getOsName()));
}

Когда мы запустим этот пример, мы получим:

org.junit.ComparisonFailure: 
Expected :run
Actual   :RUN

В этом случае наш тест не игнорируется, потому что он не прошел до того, как мы достигли вызов acceptThat(). То же самое происходит со всеми методами acceptXXX. Итак, нам нужно убедиться, что мы поместили их в нужное место внутри нашего тестового метода.

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

В этом кратком руководстве мы увидели, как мы можем условно решить, следует ли запускать тест, используя класс Assume в JUnit 4. В случае, если мы используем JUnit 5, он также доступен в версии 5.4 или выше.

«Как всегда, исходный код рассмотренных нами примеров можно найти на GitHub.