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

Порядок тестов в JUnit

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

1. Обзор

По умолчанию JUnit запускает тесты в детерминированном, но непредсказуемом порядке ( MethodSorters.DEFAULT ).

В большинстве случаев такое поведение совершенно нормально и приемлемо. Но бывают случаи, когда нам нужно обеспечить соблюдение определенного порядка.

2. Тестовый заказ в JUnit 5

В JUnit 5 мы можем использовать @TestMethodOrder для управления порядком выполнения тестов.

Мы можем использовать наш собственный MethodOrderer , как мы увидим позже.

Или мы можем выбрать один из трех встроенных ордеров:

  1. Буквенно-цифровой порядок
  2. @Заказать аннотацию
  3. Случайный порядок

2.1. Использование буквенно-цифрового порядка

JUnit 5 поставляется с набором встроенных реализаций MethodOrderer для запуска тестов в алфавитно-цифровом порядке.

Например, он предоставляет MethodOrderer.MethodName для сортировки тестовых методов на основе их имен и списков их формальных параметров :

@TestMethodOrder(MethodOrderer.MethodName.class)
public class AlphanumericOrderUnitTest {
private static StringBuilder output = new StringBuilder("");

@Test
void myATest() {
output.append("A");
}

@Test
void myBTest() {
output.append("B");
}

@Test
void myaTest() {
output.append("a");
}

@AfterAll
public static void assertOutput() {
assertEquals("ABa", output.toString());
}
}

Точно так же мы можем использовать MethodOrderer.DisplayName для сортировки методов в алфавитно-цифровом порядке на основе их отображаемых имен.

Пожалуйста, имейте в виду, что MethodOrderer.Alphanumeric — это еще одна альтернатива. Однако эта реализация устарела и будет удалена в версии 6.0.

2.2. Использование аннотации @Order

Мы можем использовать аннотацию @Order , чтобы принудительно запускать тесты в определенном порядке.

В следующем примере методы будут запускать firstTest() , затем secondTest() и, наконец , ThirdTest() :

@TestMethodOrder(OrderAnnotation.class)
public class OrderAnnotationUnitTest {
private static StringBuilder output = new StringBuilder("");

@Test
@Order(1)
void firstTest() {
output.append("a");
}

@Test
@Order(2)
void secondTest() {
output.append("b");
}

@Test
@Order(3)
void thirdTest() {
output.append("c");
}

@AfterAll
public static void assertOutput() {
assertEquals("abc", output.toString());
}
}

2.3. Использование случайного порядка

Мы также можем псевдослучайно упорядочивать методы тестирования, используя реализацию MethodOrderer.Random :

@TestMethodOrder(MethodOrderer.Random.class)
public class RandomOrderUnitTest {

private static StringBuilder output = new StringBuilder("");

@Test
void myATest() {
output.append("A");
}

@Test
void myBTest() {
output.append("B");
}

@Test
void myCTest() {
output.append("C");
}

@AfterAll
public static void assertOutput() {
assertEquals("ACB", output.toString());
}

}

На самом деле JUnit 5 использует System.nanoTime() в качестве начального значения по умолчанию для сортировки тестовых методов. Это означает, что порядок выполнения методов может не совпадать в повторяющихся тестах.

Однако мы можем настроить пользовательское начальное число, используя свойство junit.jupiter.execution.order.random.seed для создания повторяющихся сборок.

Мы можем указать значение нашего пользовательского начального числа в файле junit-platform.properties :

junit.jupiter.execution.order.random.seed=100

2.4. Использование пользовательского заказа

Наконец, мы можем использовать собственный заказ, реализуя интерфейс MethodOrderer . ** **

В нашем CustomOrder мы упорядочим тесты на основе их имен в буквенно-цифровом порядке без учета регистра:

public class CustomOrder implements MethodOrderer {
@Override
public void orderMethods(MethodOrdererContext context) {
context.getMethodDescriptors().sort(
(MethodDescriptor m1, MethodDescriptor m2)->
m1.getMethod().getName().compareToIgnoreCase(m2.getMethod().getName()));
}
}

Затем мы будем использовать CustomOrder для запуска тех же тестов из нашего предыдущего примера в порядке myATest() , myaTest() и, наконец , myBTest() :

@TestMethodOrder(CustomOrder.class)
public class CustomOrderUnitTest {

// ...

@AfterAll
public static void assertOutput() {
assertEquals("AaB", output.toString());
}
}

2.5. Установить порядок по умолчанию

JUnit 5 предоставляет удобный способ установить порядок методов по умолчанию с помощью параметра junit.jupiter.testmethod.order.default .

Точно так же мы можем настроить наш параметр в файле junit-platform.properties :

junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$DisplayName

Порядок по умолчанию будет применяться ко всем тестам, которые не квалифицированы с помощью @TestMethodOrder .

Еще одна важная вещь, о которой следует упомянуть, это то, что указанный класс должен реализовывать интерфейс MethodOrderer .

3. Тестовый заказ в JUnit 4

Для тех, кто все еще использует JUnit 4, API-интерфейсы для заказа тестов немного отличаются.

Давайте рассмотрим варианты достижения этого и в предыдущих версиях.

3.1. Использование MethodSorters.DEFAULT

Эта стратегия по умолчанию сравнивает методы тестирования, используя их хэш-коды.

В случае хеш-коллизии используется лексикографический порядок:

@FixMethodOrder(MethodSorters.DEFAULT)
public class DefaultOrderOfExecutionTest {
private static StringBuilder output = new StringBuilder("");

@Test
public void secondTest() {
output.append("b");
}

@Test
public void thirdTest() {
output.append("c");
}

@Test
public void firstTest() {
output.append("a");
}

@AfterClass
public static void assertOutput() {
assertEquals(output.toString(), "cab");
}
}

Когда мы запустим тесты в классе выше, мы увидим, что все они пройдены, включая assertOutput() .

3.2. Использование MethodSorters.JVM

Еще одна стратегия упорядочивания — MethodSorters.JVM .

Эта стратегия использует естественный порядок JVM, который может быть разным для каждого запуска :

@FixMethodOrder(MethodSorters.JVM)
public class JVMOrderOfExecutionTest {
// same as above
}

Каждый раз, когда мы запускаем тесты в этом классе, мы получаем другой результат.

3.3. Использование MethodSorters.NAME_ASCENDING

Наконец, эту стратегию можно использовать для запуска тестов в их лексикографическом порядке:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NameAscendingOrderOfExecutionTest {
// same as above

@AfterClass
public static void assertOutput() {
assertEquals(output.toString(), "abc");
}
}

Когда мы запускаем тесты в этом классе, мы видим, что все они проходят, включая assertOutput() . Это подтверждает порядок выполнения, который мы установили с помощью аннотации.

4. Вывод

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

Как всегда, примеры, использованные в этой статье, можно найти на GitHub .