Как я могу запустить все модульные тесты JUnit, кроме тех, которые заканчиваются на "IntegrationTest" в моем проекте IntelliJ IDEA, используя интегрированный тестовый бегун?

В основном я хочу запускать все тесты JUnit unit в проекте IntelliJ IDEA (исключая тесты интеграции JUnit), используя метод static suite() для JUnit. Зачем использовать метод static suite()? Поскольку я могу использовать IntelliJ IDEA JUnit для запуска всех модульных тестов в моем приложении (и легко исключить все интеграционные тесты по соглашению об именах). Код выглядит так:

package com.acme;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class AllUnitTests extends TestCase {

    public static Test suite() {
        List classes = getUnitTestClasses();
        return createTestSuite(classes);
    }

    private static List getUnitTestClasses() {
        List classes = new ArrayList();
        classes.add(CalculatorTest.class);
        return classes;
    }

    private static TestSuite createTestSuite(List allClasses) {
        TestSuite suite = new TestSuite("All Unit Tests");
        for (Iterator i = allClasses.iterator(); i.hasNext();) {
            suite.addTestSuite((Class<? extends TestCase>) i.next());
        }
        return suite;
    }

}

Метод getUnitTestClasses() должен быть перезаписан, чтобы добавить все классы проекта, расширяющие TestCase, за исключением случаев, когда имя класса заканчивается в "IntegrationTest".

Я знаю, что могу сделать это легко в Maven, например, но мне нужно сделать это в IntelliJ IDEA, чтобы я мог использовать интегрированный тестовый бегун - мне нравится зеленый бар:)

Ответ 1

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

public class ClassEnumerator {
    public static void main(String[] args) throws ClassNotFoundException {
        List<Class<?>> list = listClassesInSamePackage(Locator.class, true);

        System.out.println(list);
    }

    private static List<Class<?>> listClassesInSamePackage(Class<?> locator, boolean includeLocator) 
                                                                      throws ClassNotFoundException {

        File packageFile = getPackageFile(locator);

        String ignore = includeLocator ? null : locator.getSimpleName() + ".class";

        return toClassList(locator.getPackage().getName(), listClassNames(packageFile, ignore));
    }

    private static File getPackageFile(Class<?> locator) {
        URL url = locator.getClassLoader().getResource(locator.getName().replace(".", "/") + ".class");
        if (url == null) {
            throw new RuntimeException("Cannot locate " + Locator.class.getName());
        }

        try {
        return new File(url.toURI()).getParentFile();
        }
        catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    private static String[] listClassNames(File packageFile, final String ignore) {
        return packageFile.list(new FilenameFilter(){
            @Override
            public boolean accept(File dir, String name) {
                if (name.equals(ignore)) {
                    return false;
                }
                return name.endsWith(".class");
            }
        });
    }

    private static List<Class<?>> toClassList(String packageName, String[] classNames)
                                                             throws ClassNotFoundException {

        List<Class<?>> result = new ArrayList<Class<?>>(classNames.length);
        for (String className : classNames) {
            // Strip the .class
            String simpleName = className.substring(0, className.length() - 6);

            result.add(Class.forName(packageName + "." + simpleName));
        }
        return result;
    }
}

Ответ 2

Как разместить каждую основную группу тестов junit в своем собственном корневом пакете. Я использую эту структуру пакета в своем проекте:

test.
  quick.
    com.acme
  slow.
    com.acme

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

Ответ 3

Как насчет использования JUnit4 и Suite-Runner?

Пример:

@RunWith(Suite.class)
@Suite.SuiteClasses({
UserUnitTest.class,
AnotherUnitTest.class
})
public class UnitTestSuite {}

Я сделал небольшую оболочку Script, чтобы найти все Unit-Tests и еще один, чтобы найти тесты Integration-Tests. Взгляните на мою запись в блоге: http://blog.timomeinen.de/2010/02/find-all-junit-tests-in-a-project/

Если вы используете Spring TestContext, вы можете использовать @IfProfile Annotation для объявления различных тестов.

С уважением, Тимо Мейнен

Ответ 4

Spring реализовала отличную функцию поиска класса в PathMatchingResourcePatternResolver. Если вы используете префикс classpath *: вы можете найти все ресурсы, включая классы в заданной иерархии, и даже фильтровать их, если хотите. Затем вы можете использовать дочерние объекты AbstractTypeHierarchyTraversingFilter, AnnotationTypeFilter и AssignableTypeFilter для фильтрации этих ресурсов либо на аннотациях уровня классов, либо на интерфейсах, которые они реализуют.

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/core/type/filter/AbstractTypeHierarchyTraversingFilter.html

Ответ 5

Решение: https://github.com/MichaelTamm/junit-toolbox
Используйте следующие функции.

@RunWith(WildcardPatternSuite.class)
@SuiteClasses({"**/*.class", "!**/*IntegrationTest.class"})
public class AllTestsExceptionIntegrationSuit {
}

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