it-swarm.com.ru

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

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

Например:

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

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

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

379
卢声远 Shengyuan Lu

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

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

Как мне использовать тестовый прибор?

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

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

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

221
Pascal Thivent

Если вы избавитесь от существующего экземпляра 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");
    }
}
73
Aniket Kulkarni

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

@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() - простая функция, которая перебирает все возможные перестановки в коллекцию массивов.

48
Xiè Jìléi

Миграция на 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.

41
joro

Это одна из главных проблем, с которой я столкнулся, когда работал над 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 ()". Спасибо!

17
Aman Goel

(Пока не выпущенное) изменение https://github.com/junit-team/junit/pull/386 вводит @SortMethodsWith. https://github.com/junit-team/junit/pull/29 по крайней мере сделал заказ предсказуемым без этого (в Java 7 он может быть довольно случайным).

8
Jesse Glick

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

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

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

a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething

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

6
Zon

Посмотрите на отчет JUnit. JUnit уже организован по пакетам. Каждый пакет имеет (или может иметь) классы TestSuite, каждый из которых, в свою очередь, запускает несколько тестовых случаев. Каждый 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, которая усложняет жизнь многим разработчикам тестов.

6
Anonymous Developer

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

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

org.junit.runners.Suite

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

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

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

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

3
CharlieS

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

3
Mattk

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

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

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

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

2
kornero

С помощью 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

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

0
Walid

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

0
Martin Kersten

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

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

0
shlomi33

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

@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 { ...}
0
Arezoo Bagherzadi

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

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

0
McCoy

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

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

test12 будет запущен до test2

так:

testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond

0
pstorli