Как запустить методы тестирования в определенном порядке в JUnit4? - PullRequest
382 голосов
/ 12 сентября 2010

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

Например:

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

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

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

Ответы [ 17 ]

222 голосов
/ 12 сентября 2010

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

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

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

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

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

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

75 голосов
/ 10 июля 2014

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

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

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

43 голосов
/ 12 июня 2014

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

17 голосов
/ 24 октября 2016

Это одна из главных проблем, с которой я столкнулся, когда работал над 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 голосов
/ 17 сентября 2012

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

6 голосов
/ 06 ноября 2012

Посмотрите на отчет 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 голосов
/ 22 августа 2018

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

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

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

a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething

Вы можете найти Приведенные здесь примеры 1012 *

3 голосов
/ 19 марта 2015

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

3 голосов
/ 27 августа 2014

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

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

org.junit.runners.Suite

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...