Заказ модульных тестов в представлении Eclipse JUnit - PullRequest
38 голосов
/ 04 февраля 2009

Представление JUnit в Eclipse, кажется, упорядочивает тесты случайным образом. Как я могу заказать их по имени класса?

Ответы [ 6 ]

5 голосов
/ 07 февраля 2009

Как сказал Гари в комментариях:

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

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

Я бы хотел увидеть решение, если вы измените код плагина.

3 голосов
/ 26 сентября 2013

Одна вещь, которую можно сделать, это использовать схему JUnit 3.x. Мы использовали набор тестов, который назывался AllTests, в который вы добавляете тесты в определенном порядке. И для каждого пакета мы получили еще один AllTests. Присвоение этим комплектам тестов имени, совпадающего с пакетом, позволяет легко построить иерархию, которая должна оцениваться плагином junit.

Мне действительно не нравится, как это даже представляет методы тестирования в средстве просмотра Junit. Он должен быть в том же порядке, в котором они указаны в классе TestCase. Я заказываю эти методы в порядке важности и возможностей. Таким образом, самый неудачный метод - сначала исправить, а затем более особенный в более поздней части тестового примера.

Это действительно раздражает, что бегун тестирует их. Я сам посмотрю на него и, если найду решение, обновлю этот ответ.

Обновление:

Моя проблема с упорядочением имен методов в TestCase связана с этой: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180 (Спасибо, Оракул!).

Таким образом, в конце оракул изменил порядок методов внутри вызова class.getMethods или class.getDeclaredMethods. Теперь методы являются случайными и могут меняться между различными запусками JVM. Кажется, это связано с оптимизацией сравнения или даже является попыткой сжать имя метода - кто знает ...

Так что же осталось. Сначала можно использовать: @FixMethodOrder (из javacodegeeks.com ):

  1. @ FixMethodOrder (MethodSorters.DEFAULT) - детерминированный порядок на основе внутреннего компаратора
  2. @ FixMethodOrder (MethodSorters.NAME_ASCENDING) - в порядке возрастания имен методов
  3. @ FixMethodOrder (MethodSorters.JVM) - до 4.11 способ зависимости от порядка на основе отражения

Это глупо, но объясняет, почему люди начинают использовать схему test1TestName.

Update2

Я использую ASM, поскольку Javassist также производит случайные отсортированные методы в getMethods (). Они используют Карты внутри. С ASM я просто использую Visitor.

package org.junit.runners.model;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import com.flirtbox.ioc.OrderTest;

/**
 * @author Martin Kersten
*/
public class TestClassUtil {
public static class MyClassVisitor extends ClassVisitor {
    private final List<String> names;
    public MyClassVisitor(List<String> names) {
        super(Opcodes.ASM4);
        this.names = names;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc,
            String signature, String[] exceptions) {
        names.add(name);
        return super.visitMethod(access, name, desc, signature, exceptions);
    }
}

private static List<String> getMethodNamesInCorrectOrder(Class<?> clazz) throws IOException {
    InputStream in = OrderTest.class.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class");
    ClassReader classReader=new ClassReader(in);
    List<String> methodNames = new ArrayList<>();
    classReader.accept(new MyClassVisitor(methodNames), 0);
    return methodNames;
}

public static void sort(Class<?> fClass, List<FrameworkMethod> list) {
    try {
        final List<String> names = getMethodNamesInCorrectOrder(fClass);
        Collections.sort(list, new Comparator<FrameworkMethod>() {
            @Override
            public int compare(FrameworkMethod methodA, FrameworkMethod methodB) {
                int indexA = names.indexOf(methodA.getName());
                int indexB = names.indexOf(methodB.getName());
                if(indexA == -1)
                    indexA = names.size();
                if(indexB == -1)
                    indexB = names.size();
                return indexA - indexB;
            }
        });
    } catch (IOException e) {
        throw new RuntimeException("Could not optain the method names of " + fClass.getName() + " in correct order", e);
    }
}
}

Просто поместите это в вашу папку src / test / java в пакете org.junit.runners.model. Теперь скопируйте org.junit.runners.model.TestClass из библиотеки junit 4.5 в тот же пакет и измените его конструктор, добавив процедуру сортировки.

 public TestClass(Class<?> klass) {
    fClass= klass;
    if (klass != null && klass.getConstructors().length > 1)
        throw new IllegalArgumentException(
                "Test class can only have one constructor");

    for (Class<?> eachClass : getSuperClasses(fClass))
        for (Method eachMethod : eachClass.getDeclaredMethods())
            addToAnnotationLists(new FrameworkMethod(eachMethod));

            //New Part
    for(List<FrameworkMethod> list : fMethodsForAnnotations.values()) {
        TestClassUtil.sort(fClass, list);
    }

    //Remove once you have verified the class is really picked up
    System.out.println("New TestClass for " + klass.getName());

}

Вот, пожалуйста. Теперь у вас есть хорошо отсортированные методы в том порядке, в котором они объявлены в Java-файле. Если вам интересно, путь к классу обычно задается таким образом, что загрузчик классов сначала рассматривает все содержимое вашей папки src (target или bin). Поэтому, определяя один и тот же пакет и один и тот же класс, вы можете «переопределить» каждый класс / интерфейс в любой используемой вами библиотеке. Вот и весь трюк!

Update3 Я смог получить представление дерева каждого пакета и каждого класса в правильном порядке.

  • Идея состоит в том, чтобы создать подкласс ParentRunner, а затем добавить в него все классы, которые вы определили как общедоступные и с методами, аннотированными с помощью test.
  • Добавьте метод getName (), возвращающий только имя пакета класса, представляемого вашим исполнителем пакета (поэтому вы видите дерево как дерево пакетов без имени класса пакета).
  • Проверьте подкаталоги, если вы найдете определенный класс комплекта (я использую AllTests для всех классов комплекта).
  • Если вы не нашли класс комплекта в подкаталоге, проверьте все его подкаталоги, таким образом, вы не пропустите пакет, содержащий тесты, если родительский каталог не содержит комплект.

Вот и все. Класс набора, который я добавляю везде: @RunWith(MySuiteRunner.class) public class AllTests { }

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

2 голосов
/ 05 февраля 2009

Если вам действительно нужна жесткая зависимость между тестом JUnit, попробуйте расширение JExample

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

Вы можете установить его в Eclipse , для Junit4.4 или 4.5.

import jexample.Depends;

  @Test
  @Depends("#testEmpty") 
  public Stack<Integer> testPush(Stack<Integer> $) { 
      $.push(42); 
      assertFalse($.isEmpty()); 
      return $; 
  } 

Как уже упоминалось в этой статье IBM "В погоне за качеством кода: JUnit 4 vs. TestNG" :

Одна вещь, которую пытается достичь инфраструктура JUnit, это тестовая изоляция .
С другой стороны, это очень затрудняет указание порядка выполнения тестового примера, что важно для любого вида зависимого тестирования.
Разработчики использовали разные методы, чтобы обойти это, например, указание контрольных примеров в алфавитном порядке или сильная зависимость от приборов (@Before @After) для правильной настройки.

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

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

2 голосов
/ 04 февраля 2009

Марк написал:

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

Оценка верна. Но вы не можете отсортировать свой юнит-тест. Нельзя спекулировать о порядке исполнения.

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

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

1 голос
/ 11 января 2015

Заказ тестов в представлении JUnit был представлен как ошибка # 386453 в Eclipse Bugzilla . Комментирование и / или голосование могут помочь лучше понять проблему.

0 голосов
/ 09 февраля 2011

Я также искал решение для этого и обнаружил своего рода трещину по приведенному ниже URL. Я не знаю, работает ли он для вас или нет, но он работал для меня в Spring Tool Suite 2.5.2.

http://osdir.com/ml/java.junit.user/2002-10/msg00077.html

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