Могу ли я избежать запуска тестов junit дважды в eclipse при использовании TestSuite?

Мне нужно выполнить некоторую инициализацию для каждого пакета (начиная с веб-сервера). Он отлично работает, за исключением того, что когда я запускаю все тесты в своем проекте в eclipse, мои тесты выполняются дважды. Мой набор тестов выглядит примерно так:

@RunWith(Suite.class)
@Suite.SuiteClasses({
   SubtestOne.class,
   SubtestTwo.class
})
public class TestSuite
{
   [...]
}

public class SubtestOne
{
   @Test public void testOne() { [...] }
}

public class SubtestTwo
{
   @Test public void testTwo() { [...] }
}

Когда я запускаю весь тест в проекте в eclipse, это приводит к тому, что плагин junit запускает тесты дважды:

  • SubtestOne
  • SubtestTwo
  • TestSuite
    • SubtestOne
    • SubtestTwo

Возможно ли, чтобы "запустить все тесты в проекте" не выполнялось дважды в двух тестах? Я хочу, чтобы мои вспомогательные тесты выполнялись только как часть пакета.

Ответ 1

Нет, тестовый класс всегда запускается напрямую, а затем через "ссылку" в пакете. Это так, как ожидалось.

Одно решение может установить в конфигурации запуска только запуск тестов из пакета, который содержит ваши пакеты. Откройте конфигурацию прогона и выберите Run all tests in the selected project, package or source folder, затем нажмите Search... и выберите пакет.

Ответ 2

Вам нужен пакет в первую очередь? в зависимости от того, когда вы нажмете для запуска всех (класс, пакет или src/test/java), все базовые тесты будут выполнены. Итак, какой смысл иметь пакет?

Ответ 3

У меня есть идея для вас. На самом деле вы не хотите запускать этот тестовый пример в качестве автономных тестовых случаев. Вы можете сделать следующее.

Отметьте тестовые примеры аннотацией @RunWith(DoNothingRunner.class)

Implment DoNothingRunner следующим образом:

public class DoNothingRunner extends Runner {
    public Description getDescription() {
              return "do nothing";
        }
    public void run(RunNotifier notifier) {
            // indeed do nothing
        }
}

Я не пробовал это лично, но надеюсь, что это сработает.

Ответ 4

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

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

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

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

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

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.Test1.class, AllTests.InSuiteOnly.Test2.class})
public class AllTests
{
    static class InSuiteOnly
    {
        public static class Test1
        {
            @Test
            public void test1()
            {
                //...
            }
        }

        public static class Test2
        {
            @Test
            public void test2()
            {
                //...
            }
        }
    }
}

Многие люди, вероятно, возражают против всех тестов, которые должны находиться внутри одного исходного файла. Что делать, если я хочу поддерживать отдельные тестовые классы JUnit, которые сами не выполняются, но все равно выполняются внутри набора тестов? Простое решение состоит в том, чтобы сделать отдельные тестовые классы абстрактными (public/non-public не имеет значения), чтобы JUnit не выполнял их, и внутри набора тестов мы просто используем конкретные подклассы исходных абстрактных тестовых классов:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.SuiteTest1.class, AllTests.InSuiteOnly.SuiteTest2.class})
public class AllTests
{
    static class InSuiteOnly
    {
        public static class SuiteTest1 extends Test1 {}
        public static class SuiteTest2 extends Test2 {}
    }
}

abstract class Test1
{
    @Test
    public void test1()
    {
        //...
    }
}

abstract class Test2
{
    @Test
    public void test2()
    {
        //...
    }
}

Эта схема работает с Maven, Eclipse и всеми другими средами, которые либо прямо используют бегунов JUnit, либо реализуют свои собственные бегуны, которые внимательно следят за оригинальным поведением и семантикой JUnit.

Ответ 5

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

@RunWith(Suite.class)
@Suite.SuiteClasses({
    AXXSuite.class,
    BXXSuite.class,
    CXXSuite.class
})
public class AllSuites {    

}