Указание порядка джунтирования 4 тестов на уровне метода (не на уровне класса) - PullRequest
39 голосов
/ 22 июня 2010

Я знаю, что это плохая практика, но это нужно сделать, или мне нужно переключиться на testng.Есть ли способ, аналогичный testSuite в JUnit 3, указать порядок тестов, которые должны быть выполнены в классе?

Ответы [ 6 ]

62 голосов
/ 07 сентября 2012

Я вижу несколько причин для этого, особенно при использовании JUnit для запуска функциональных тестов или тестирования постоянных объектов. Например, рассмотрим объект Article, который сохраняется в каком-то постоянном хранилище. Если бы я хотел проверить функциональность вставки, обновления и удаления объекта Article, следуя принципу модульного теста «все тесты должны быть переупорядочиваемыми и тестировать только определенную часть функциональности», у меня было бы три теста:

  • testInsertArticle()
  • testUpdateArticle()
  • testDeleteArticle()

Однако, чтобы протестировать функциональность обновления, мне сначала нужно вставить статью. Чтобы проверить функциональность удаления, мне также нужно вставить статью. Таким образом, на практике функциональность вставки уже проверена как в testUpdateArticle(), так и в testDeleteArticle(). Затем возникает соблазн просто создать тестовый метод testArticleFunctionality(), который все это делает, но такие методы в конечном итоге получат огромный объем (и они не будут просто тестировать часть функциональности объекта Article).

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

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

Вот как это используется. Это позволяет избежать необходимости называть такие тесты, как AA_testInsert(), AB_testUpdate(), AC_testDelete(), ..., ZC_testFilter() и т. Д.

@RunWith(OrderedRunner.class)
public class SomethingTest {
    @Test
    @Order(order=2)
    public void testUpdateArticle() {
        // test update
    }

    @Test
    @Order(order=1)
    public void testInsertArticle() {
        // test insert
    }

    @Test
    @Order(order=3)
    public void testDeleteArticle() {
        // test delete
    }
}

Независимо от того, как эти тесты помещаются в файл, они всегда будут запускаться как order=1 первый, order=2 второй и последний order=3, независимо от того, запускаете ли вы их из Eclipse, с помощью Ant или любого другого Другой путь.

Реализация следует. Сначала аннотация Order.

@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
    public int order();
}

Затем модифицированный OrderedRunner.

public class OrderedRunner extends BlockJUnit4ClassRunner {
    public OrderedRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        Collections.sort(list, 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 list;
    }
}
62 голосов
/ 02 сентября 2010

Если вы уверены, что действительно хотите сделать это: может быть, есть лучший способ, но это все, что я мог придумать ...

JUnit4 имеет аннотацию: @RunWith, которая позволяет переопределить Runner по умолчанию для ваших тестов.

В вашем случае вы захотите создать специальный подкласс BlockJunit4ClassRunner и переопределить computeTestMethods(), чтобы возвращать тесты в нужном вам порядке.их казнили.Например, скажем, я хочу выполнить свои тесты в обратном алфавитном порядке:

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List computeTestMethods() {
        List list = super.computeTestMethods();
        List copy = new ArrayList(list);
        Collections.sort(copy, new Comparator() {
            public int compare(FrameworkMethod o1, FrameworkMethod o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        return copy;
    }
}
@RunWith(OrderedRunner.class)
public class OrderOfTest {
    @Test public void testA() { System.out.println("A"); }
    @Test public void testC() { System.out.println("C"); }
    @Test public void testB() { System.out.println("B"); }
}

Запуск этого теста приводит к:

C
B
A

Для вашего конкретного случая вы хотели быкомпаратор, который сортирует тесты по имени в том порядке, в котором вы хотите их выполнить.(Я бы предложил определить компаратор, используя что-то вроде класса Google Guava Ordering.explicit("methodName1","methodName2").onResultOf(...);, где onResultOf предоставляет функцию, которая преобразует FrameworkMethod в его имя ... хотя, очевидно, вы можете реализовать это любым способом.

26 голосов
/ 02 февраля 2013

Начиная с версии 4.11 JUnit, можно влиять на порядок выполнения теста, пометив класс с помощью @FixMethodOrder и указав любой из доступных MethodSorters.См. эту ссылку для более подробной информации.

4 голосов
/ 20 марта 2014

Использование junit 4.11 новой аннотации @FixMethodOrder позволяет установить определенный порядок:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
1 голос
/ 24 июля 2015

Йоскарссон и Майкл D пишут в моем репозитории на github. Я надеюсь, что они не возражают. Я также предоставляю заказанную версию для Параметризованного класса. Он уже используется как зависимость maven

<repositories>
    <repository>
        <id>git-xxx</id>
        <url>https://github.com/crsici/OrderedRunnerJunit4.11/raw/master/</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.sici.org.junit</groupId>
    <artifactId>ordered-runner</artifactId>
    <version>0.0.1-RELEASE</version>
</dependency>
1 голос
/ 12 ноября 2012

Если вы хотите запускать тесты junit по порядку «так, как они представлены в вашем исходном коде», и не хотите изменять код тестов, см. Мое примечание об этом здесь:Как запускать тесты junit по порядку, как они представлены в вашем исходном коде

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

...