Как запустить тестовые методы в определенном порядке в JUnit4?

Я хочу выполнить тестовые методы, которые аннотируются @Test в определенном порядке.

Например:

public class MyTest {
    @Test public void test1(){}
    @Test public void test2(){}
}

Я хочу обеспечить запуск test1() до test2() при каждом запуске MyTest, но я не мог найти аннотацию, например @Test(order=xx).

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

Ответ 1

Я думаю, что это очень важная функция для JUnit, если автор JUnit не хочет, чтобы функция заказа, почему?

Я не уверен, что с JUnit существует чистый способ, насколько мне известно, JUnit предполагает, что все тесты могут выполняться в произвольном порядке. Из FAQ:

Как использовать тестовое оборудование?

(...) Порядок вызова тестовых методов не гарантируется, поэтому testOneItemCollection() может быть выполнено до testEmptyCollection(). (...)

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

Если вы действительно хотите пойти в этом направлении, подумайте об использовании TestNG, поскольку он поддерживает запуск методов тестирования в любом произвольном порядке изначально (и такие вещи, как указание того, что методы зависят от групп методов). Седрик Боуст объясняет, как это сделать в порядке выполнения тестов в testng.

Ответ 2

Junit 4.11 поставляется с аннотацией @FixMethodOrder. Вместо использования пользовательских решений просто обновите версию junit и отметьте класс test с помощью FixMethodOrder(MethodSorters.NAME_ASCENDING). Подробнее см. примечания к выпуску.

Вот пример:

import org.junit.runners.MethodSorters;

import org.junit.FixMethodOrder;
import org.junit.Test;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void firstTest() {
        System.out.println("first");
    }

    @Test
    public void secondTest() {
        System.out.println("second");
    }
}

Ответ 3

Если вы избавитесь от существующего экземпляра Junit и загрузите JUnit 4.11 или выше в пути сборки, следующий код выполнит методы тестирования в порядке их имен, отсортированных в порядке возрастания:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void testAcreate() {
        System.out.println("first");
    }
    @Test
    public void testBupdate() {
        System.out.println("second");
    }
    @Test
    public void testCdelete() {
        System.out.println("third");
    }
}

Ответ 4

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

@Test public void test1() { ... }
@Test public void test2() { test1(); ... }

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

Например,

void test1(); 
void test2(); 
void test3(); 


@Test
public void testOrder1() { test1(); test3(); }

@Test(expected = Exception.class)
public void testOrder2() { test2(); test3(); test1(); }

@Test(expected = NullPointerException.class)
public void testOrder3() { test3(); test1(); test2(); }

Или, полный тест всех перестановок:

@Test
public void testAllOrders() {
    for (Object[] sample: permute(1, 2, 3)) {
        for (Object index: sample) {
            switch (((Integer) index).intValue()) {
                case 1: test1(); break; 
                case 2: test2(); break; 
                case 3: test3(); break; 
            }
        }
    }
}

Здесь permute() - простая функция, которая выполняет итерацию всех возможных перестановок в коллекцию массива.

Ответ 5

Перенос в TestNG кажется лучшим, но я не вижу здесь ясного решения для jUnit. Вот наиболее читаемое решение/форматирование, которое я нашел для jUnit:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
    @Test
    void stage1_prepareAndTest(){};

    @Test
    void stage2_checkSomething(){};

    @Test
    void stage2_checkSomethingElse(){};

    @Test
    void stage3_thisDependsOnStage2(){};

    @Test
    void callTimeDoesntMatter(){}
}

Это гарантирует, что методы stage2 вызываются после stage1 и до stage3.

Ответ 6

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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list);
        Collections.sort(copy, new Comparator<FrameworkMethod>() {

            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null) {
                    return -1;
                }

                return o1.order() - o2.order();
            }
        });
        return copy;
    }
}

также создайте интерфейс, как показано ниже:

 @Retention(RetentionPolicy.RUNTIME)


@Target({ ElementType.METHOD})

public @interface Order {
public int order();
}

Теперь предположим, что у вас есть класс A, где вы написали несколько тестовых примеров, как показано ниже:

(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)

void method(){

//do something

}

}

Итак, выполнение начнется с метода с именем "method()". Спасибо!

Ответ 8

JUnit в настоящее время позволяет тестовым методам выполнять упорядочение с использованием аннотаций классов:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)

По умолчанию методы испытаний запускаются в алфавитном порядке. Итак, чтобы установить определенный порядок методов, вы можете назвать их как:

a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething

Вы можете найти примеры здесь.

Ответ 9

Посмотрите отчет JUnit. JUnit уже организован пакетом. Каждый пакет имеет (или может иметь) классы TestSuite, каждый из которых, в свою очередь, запускает несколько TestCases. Каждая TestCase может иметь несколько методов тестирования формы public void test*(), каждая из которых фактически станет экземпляром класса TestCase, к которому они принадлежат. Каждый тестовый метод (экземпляр TestCase) имеет имя и критерии прохождения/отказа.

То, что требуется моему руководству, - это концепция отдельных TestStep элементов, каждая из которых сообщает свои собственные критерии прохождения/отказа. Неисправность любого этапа тестирования не должна препятствовать выполнению последующих этапов тестирования.

В прошлом разработчики тестов в моей позиции организовали классы TestCase в пакеты, соответствующие части (-ам) тестируемого продукта, создали класс TestCase для каждого теста и сделали каждый тестовый метод отдельным "шагом" в тест, в комплекте с его собственными критериями прохождения/отказа в выходе JUnit. Каждая TestCase является автономным "тестом", но отдельные методы или тестовые "шаги" в TestCase должны выполняться в определенном порядке.

Методами TestCase были шаги TestCase, и разработчики тестов получили отдельный критерий прохождения/отказа на каждый шаг теста. Теперь шаги тестирования смешаны, и тесты (конечно) не работают.

Например:

Class testStateChanges extends TestCase

public void testCreateObjectPlacesTheObjectInStateA()
public void testTransitionToStateBAndValidateStateB()
public void testTransitionToStateCAndValidateStateC()
public void testTryToDeleteObjectinStateCAndValidateObjectStillExists()
public void testTransitionToStateAAndValidateStateA()
public void testDeleteObjectInStateAAndObjectDoesNotExist()
public void cleanupIfAnythingWentWrong()

Каждый метод тестирования утверждает и сообщает о своих собственных критериях прохождения/отказа. Свертывание этого в "один большой тестовый метод" для упорядочения теряет степень детализации критерия прохождения/отказа каждого "шага" в сводном отчете JUnit.... и это расстраивает моих менеджеров. В настоящее время они требуют другой альтернативы.

Может ли кто-нибудь объяснить, как JUnit с упорядоченным методом тестирования скремблирования будет поддерживать отдельные критерии прохождения/отказа каждого последовательного тестового шага, как показано выше и требуется моим руководством?

Независимо от документации, я рассматриваю это как серьезную регрессию в структуре JUnit, которая усложняет жизнь многим разработчикам тестов.

Ответ 10

То, что вы хотите, вполне разумно, когда тестовые примеры выполняются как набор.

К сожалению, нет времени, чтобы дать полное решение прямо сейчас, но посмотрите на класс:

org.junit.runners.Suite

Позволяет вам вызывать тестовые примеры (из любого тестового класса) в определенном порядке.

Они могут использоваться для создания функциональных, интеграционных или системных тестов.

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

Мы повторно используем/наследуем один и тот же код для модульных, интеграционных и системных тестов, иногда управляемых данными, иногда управляемых и иногда выполняемых как набор.

Ответ 11

Не уверен, что согласен, если я хочу протестировать "Загрузка файлов", а затем протестировать "Данные, вставленные путем загрузки файлов", почему я не хочу, чтобы они были независимыми друг от друга? Совершенно разумно, я думаю, чтобы иметь возможность запускать их отдельно, а не как в случае с Goliath.

Ответ 12

Смотрите мое решение здесь: "Junit и java 7."

В этой статье я описываю, как запускать junit-тесты по порядку - "как в вашем исходном коде". Тесты будут выполняться, чтобы ваши тестовые методы отображались в файле класса.

http://intellijava.blogspot.com/2012/05/junit-and-java-7.html

Но, как сказал Паскаль Тивент, это не очень хорошая практика.

Ответ 13

Обновление JUnit 5 (и мое мнение)

Я думаю, что это очень важная особенность для JUnit, если автор JUnit почему не нужна функция заказа?

По умолчанию библиотеки модульного тестирования не пытаются выполнять тесты в порядке, указанном в исходном файле.
JUnit 5 как JUnit 4 работает таким образом. Почему? Потому что, если порядок имеет значение, это означает, что некоторые тесты связаны между собой, и это нежелательно для модульных тестов.
Таким образом, функция @Nested, представленная JUnit 5, следует тому же подходу по умолчанию.

Но для интеграционных тестов порядок метода тестирования может иметь значение, так как метод теста может изменить состояние приложения так, как этого требует другой метод теста. Например, когда вы пишете интеграционный тест для обработки заказа в интернет-магазине, первый метод тестирования, который должен быть выполнен, - это регистрация клиента, второй - добавление товаров в корзину, а последний - проверка. Если исполнитель теста не соблюдает этот порядок, сценарий тестирования имеет недостатки и завершится ошибкой.
Таким образом, в JUnit 5 (из версии 5.4) у вас все равно есть возможность установить порядок выполнения, пометив тестовый класс с помощью @TestMethodOrder(OrderAnnotation.class) и указав порядок с помощью @Order(numericOrderValue) для методов, которые порядок имеет значение.

Например:

@TestMethodOrder(OrderAnnotation.class) 
class FooTest {

    @Order(3)
    @Test
    void checkoutOrder() {
        System.out.println("checkoutOrder");
    }

    @Order(2)
    @Test
    void addItemsInBasket() {
        System.out.println("addItemsInBasket");
    }

    @Order(1)
    @Test
    void createUserAndLogin() {
        System.out.println("createUserAndLogin");
    }
}

Вывод:

createUserAndLogin

addItemsInBasket

checkoutOrder

Кстати, указание @TestMethodOrder(OrderAnnotation.class) выглядит не нужным (по крайней мере, в версии 5.4.0, которую я тестировал).

Примечание
О вопросе: является ли JUnit 5 лучшим выбором для написания интеграционных тестов? Я не думаю, что это должен быть первый инструмент, который следует рассмотреть (Cucumber и co часто могут принести более специфическую ценность и возможности для интеграционных тестов), но в некоторых интеграционных тестах достаточно инфраструктуры JUnit. Так что это хорошая новость, что эта функция существует.

Ответ 14

Я прочитал несколько ответов и согласен с тем, что это не самая лучшая практика, но самый простой способ заказать ваши тесты - и то, как JUnit запускает тесты по умолчанию, - это алфавитное имя по возрастанию.

Итак, просто назовите свои тесты в алфавитном порядке, который вы хотите. Также обратите внимание, что имя теста должно начинаться со словом test. Просто следите за цифрами

test12 будет выполняться до test2

так:

testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond

Ответ 15

Пожалуйста, ознакомьтесь с этим: https://github.com/TransparentMarket/junit. Он запускает тест в том порядке, в котором они указаны (определяется в файле скомпилированного класса). Кроме того, в нем есть пакет AllTests для запуска тестов, определенных в первом пакете. Используя реализацию AllTests, вы можете расширить решение и фильтровать свойства (мы использовали аннотации @Fast, но они еще не были опубликованы).

Ответ 16

Вот расширение JUnit, которое может вызвать желаемое поведение: https://github.com/aafuks/aaf-junit

Я знаю, что это противоречит авторам философии JUnit, но при использовании JUnit в средах, которые не являются строгим модульным тестированием (как это практикуется на Java), это может быть очень полезно.

Ответ 17

В итоге я подумал, что мои тесты не выполняются по порядку, но правда в том, что беспорядок был в моих асинхронных заданиях. При работе с concurrency вам необходимо выполнить проверку concurrency между вашими тестами. В моем случае задания и тесты совместно используют семафор, поэтому следующие тесты зависают, пока запущенное задание не освободит блокировку.

Я знаю, что это не полностью связано с этим вопросом, но, возможно, может помочь настроить правильную проблему.

Ответ 18

вы можете использовать один из этих кодов:

@FixMethodOrder(MethodSorters.JVM)OR '@FixMethodOrder(MethodSorters.DEFAULT)' OR '@FixMethodOrder(MethodSorters.NAME_ASCENDING)' before your test class like this:


@FixMethodOrder(MethodSorters.NAME_ASCENDING)


public class BookTest { ...}

Ответ 19

Вы можете сортировать методы с @FixMethodOrder(MethodSorters.NAME_ASCENDING) аннотации @FixMethodOrder(MethodSorters.NAME_ASCENDING). Подобно,

@FixMethodOrder(MethodSorters.DEFAULT)

открытый класс DefaultOrderOfExecutionTest {приватная статическая 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");
}

}

Вы можете выполнить сортировку тремя способами:

  1. MethodSorters.DEFAULT - эта стратегия по умолчанию сравнивает методы тестирования, используя их хэш-коды. В случае коллизии хэшей используется лексикографический порядок.
  2. MethodSorters.JVM - в этой стратегии используется естественное упорядочение JVM, которое может быть разным для каждого прогона.
  3. MethodSorters.NAME_ASCENDING - эту стратегию можно использовать для запуска теста в их лексикографическом порядке.

Для более подробной информации, пожалуйста, обратитесь: Порядок испытаний в JUnit

Ответ 20

На всякий случай, если вы спрашиваете об этом, потому что вы хотите сначала выполнить отладочные тесты для отладки, в большинстве IDE есть такая возможность. Я использую Eclipse и на вкладке JUnit после запуска ваших тестов в правом верхнем углу появляется небольшая иконка "Rerun Tests - Failures First".

Ответ 21

С помощью JUnit 5.4 вы можете указать порядок:

@Test
@Order(2)
public void sendEmailTestGmail() throws MessagingException {

вам просто нужно аннотировать свой класс

@TestMethodOrder(OrderAnnotation.class)

https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order

Я использую это в своем проекте, и это работает очень хорошо!