Параллельное выполнение тестов junit в сборке Maven?

Я использую JUnit 4.4 и Maven, и у меня есть большое количество длительных интеграционных тестов.

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

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

Есть какой-либо способ сделать это?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
110
0
79 498
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

TestNG может это сделать (это был мой первый рефлекс - потом я увидел, что у вас уже много тестов).

Для JUnit посмотрите параллельный джунит.

К сожалению, это не ответ на вопрос, который я задаю. parallel-junit работает только в одном тестовом классе. TestNG также работает только в одном классе, и мои тесты не являются тестами TestNG.

krosenvold 08.01.2009 14:42

@PlatinumAzure: Я обновил ссылку. Я не знаю, как поддерживается этот проект. Другой вопрос недавно был задан распределить выполнение тестов junit на нескольких машинах.

philant 24.05.2012 11:16

Вы можете изменить свой тест на TestNg за минуту (вам просто нужно изменить импорт), TestNG - лучший вариант для параллельного тестирования.

Вы можете попробовать Gridgain, который позволяет вам распределять тесты по вычислительной сетке.

Я попробовал решение GridGain и столкнулся с двумя серьезными проблемами. Во-первых, вы должны указать GridGain исключить из пути к классам вашей грид-задачи все, что также использует GridGain, например Spring и много всего, что связано с Apache Commons. Во-вторых, загрузка классов по сети, хотя и является блестящей идеей, не работает для библиотек, которые хотят искать путь к классам, например Spring

Graham Lea 20.12.2010 02:24
Ответ принят как подходящий

Начиная с junit 4.7, теперь можно запускать тесты параллельно без использования TestNG. На самом деле это стало возможным с версии 4.6, но в 4.7 внесен ряд исправлений, которые сделают это жизнеспособным вариантом. Вы также можете запускать параллельные тесты с помощью spring, о которых вы можете прочитать о здесь

На связанной странице сказано: «для большинства двухъядерных решений работа с параллельными потоками в настоящее время никогда не бывает быстрее, чем работа без потоков». Так ли это до сих пор?

Raedwald 04.04.2011 18:00

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

Dave 04.05.2011 22:46

@Raedwald Не ожидайте, что тоже будет слишком много для коротких модульных тестов без привязки к io, - это то, что я пытаюсь сказать. Более новые версии surefire также лучше / эффективнее, чем 2.5, описанные в сообщении, поэтому вы можете получить немного лучшие результаты.

krosenvold 04.05.2011 22:54

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

Cory Kendall 14.11.2015 03:16

@krosenvold ссылка? Я изо всех сил пытаюсь найти встроенное решение.

Ilan Biala 03.06.2017 05:11

темпус-фугит предлагает нечто подобное, подробности смотрите в документации. Он основан на JUnit 4.7, и вы просто помечаете свой тест как @RunWith(ConcurrentTestRunner).

Ваше здоровье

Вы можете проверить библиотеку с открытым исходным кодом - Балансировщик нагрузки. Он делает именно то, о чем вы просите, - параллельно запускает разные тестовые классы. Это интегрируется на уровне ant-junit, так что вам ни в коем случае не нужно менять свои тесты. Я один из авторов библиотеки.

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

Наконец, как решили эту проблему до сих пор?

Используйте плагин maven:

<build>
    <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.7.1</version>
        <configuration>
            <parallel>classes</parallel>
            <threadCount>5</threadCount>
        </configuration>
    </plugin>
    </plugins>
</build>

<parallel> на самом деле поддерживается surefire, если вы используете Junit 4.7 или новее. верный гид

jontejj 13.04.2013 21:18

Вдохновленный экспериментальным бегуном Параллельный компьютер от JUnit, я создал свои собственные бегуны ParallelSuite и Параллельный. Используя эти бегуны, можно легко распараллелить наборы тестов и параметризованные тесты.

ParallelSuite.java

public class ParallelSuite extends Suite {

    public ParallelSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {

        super(klass, builder);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(4);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

ParallelParameterized.java

public class ParallelParameterized extends Parameterized {

    public ParallelParameterized(Class<?> arg0) throws Throwable {

        super(arg0);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(8);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

Использование простое. Просто измените значение аннотации @Бежать с на один из этих классов Параллельный *.

@RunWith(ParallelSuite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {}

Вы можете запускать тесты параллельно, используя ParallelComputer, предоставляемый самим Junit. Вот небольшой фрагмент, с которого можно начать.

Class[] cls = { TestCase1.class, TestCase2.class };
Result result = JUnitCore.runClasses(ParallelComputer.classes(), cls);
List<Failure> failures = result.getFailures();

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

Обратите внимание, что при этом все тестовые примеры будут запускаться параллельно, если у вас есть какие-либо зависимости между разными тестами, это может привести к ложным срабатываниям. В любом случае вам НЕ СЛЕДУЕТ проводить взаимозависимые тесты.

Другой вариант: Punner, новый параллельный бегун для Junit и плагин для maven. Вам не нужно менять свой код, скопируйте его в свой pom.xml:

<!-- Disable default surefire based testing -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.20</version>
  <configuration>
    <skip>true</skip>
  </configuration>
</plugin>

<plugin>
  <groupId>com.github.marks-yag</groupId>
  <artifactId>punner-maven-plugin</artifactId>
  <version>${version}</version>
  <configuration>
  </configuration>
  <executions>
    <execution>
      <id>test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
    </execution>
  </executions>
</plugin>

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

Punner уменьшит выходные данные консоли mvn, например:

[INFO] --- punner-maven-plugin:0.9.13:test (test) @ ipc ---
[INFO] Punner report directory: /Users/guile/workspace/ipc/target/punner-reports
[INFO]
[INFO] com.github.yag.ipc.IPCTest.testConnectionHandler.............. PASSED
[INFO] com.github.yag.ipc.IPCTest.testSequence....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testPartialContent................. PASSED
[INFO] com.github.yag.ipc.IPCTest.testResponseContent................ PASSED
[INFO] com.github.yag.ipc.IPCTest.testPingPong....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerClose.................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeat............ PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientReconnect................ PASSED
[INFO]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.952 sec, Time saved: 25.919 sec.

Punner производит надежно совместимые результаты, вы также можете получить необработанные данные журнала и отчет в формате уценки из каталога отчетов:

➜  ipc git:(develop) ll target/punner-reports
total 104
-rw-r--r--   1 guile  staff    11K Oct 15 23:07 TEST-com.github.yag.ipc.IPCTest.xml
-rw-r--r--   1 guile  staff   298B Oct 15 23:07 com.github.yag.ipc.IPCTest.txt
drwxr-xr-x  12 guile  staff   384B Oct  8 00:50 logs
-rw-r--r--   1 guile  staff    33K Oct 15 23:07 report.md

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

Punner пока не поддерживает некоторые расширенные функции. Я очень рад, если вы попробуете и оставите мне отзыв.

Другие вопросы по теме