Виконувати параметри тестів з джуніту паралельно в будівлі Maven?


110

Я використовую JUnit 4.4 та Maven, і у мене є велика кількість тривалих інтеграційних тестів.

Що стосується паралелізації наборів тестів, то існує декілька рішень, які дозволяють мені паралельно проводити кожен метод тестування в одному тестовому класі. Але все це вимагає, щоб я міняв тести так чи інакше.

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

Чи можна це зробити?

Відповіді:


75

Використовуйте плагін 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>

12
<parallel> насправді підтримується surefire, якщо ви використовуєте Junit 4.7 або новішої версії.
guidefire

42

З липня 4.7 тепер можна запускати тести паралельно без використання TestNG. Насправді це можливо з 4.6, але існує ряд виправлень, які робляться в 4.7, що зробить її життєздатною можливістю. Ви також можете провести паралельні тести з весною, про які ви можете прочитати тут


1
На пов'язаній сторінці написано, що "для більшості двоядерних рішень, запуску з паралельними потоками в даний час ніколи не буває швидше, ніж запуск без потоків". Це все-таки так?
Raedwald

2
Я б подумав, що якщо ваші тести роблять якусь IO, вони все одно отримають користь. Наприклад, якщо ваші одиничні тести більше схожі на тести інтеграції і потрапляють у базу даних, паралельний запуск повинен прискорити їх.
Дейв

@Raedwald Не чекаю занадто багато для коротких тестів, не пов'язаних з іоном, те, що я намагаюся сказати. Новіші версії верхової пожежі також краще / ефективніше, ніж 2,5, описані в публікації, тому ви можете отримати трохи кращі результати.
krosenvold

3
Ви заявляєте, що це можливо, але чи можете ви включити посилання на пояснення як? Ваше друге посилання для "з весною", яке мене не цікавить.
Cory Kendall

@krosenvold посилання? Я намагаюся знайти вбудоване рішення.
Ілан Білала

10

Натхненний експериментальним бігуном ParallelComputer JUnit, я створив власні бігуни ParallelSuite та ParallelParameterized . Використовуючи ці бігуни, можна легко паралелізувати тестові набори та параметризовані тести.

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 на один із цих класів Parallel * .

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

5

tempus-fugit пропонує щось подібне, ознайомтеся з документами. Він покладається на JUnit 4.7, і ви просто позначите свій тест @RunWith(ConcurrentTestRunner).

Ура


3

Ви можете перевірити бібліотеку з відкритим кодом - тестовий балансир . Це робить саме те, що ви просите, паралельно запускайте різні тестові класи. Це інтегрується на рівні мурашника, щоб ні в якому разі не потрібно міняти свої тести. Я один із авторів бібліотеки.

Крім того, подумайте про те, щоб не запускати їх у потоках, оскільки вам може знадобитися пісочниця рівня процесу. Наприклад, якщо ви потрапляєте на БД у своїх тестах інтеграції, ви не хочете, щоб один тест вийшов з ладу, оскільки інший тест додав деякі дані в інший потік. У більшості випадків тести не пишуться з огляду на це.

Нарешті, як вирішили цю проблему досі?


2

TestNG може це зробити (це був мій перший рефлекс - тоді я побачив, що у вас вже багато тестів).

Для JUnit подивіться на паралель-junit .


3
На жаль, це не відповідь на запитання, яке я задаю. Паралельно-юніт працює лише в одному тестовому класі. TestNG також працює лише в одному класі, і мої тести не є тестами TestNG.
krosenvold

@PlatinumAzure: я оновив посилання. Я не знаю, як підтримується цей проект. Нещодавно було задано ще одне запитання щодо розподілу виконання тестів на день на декількох машинах .
благодійник

2

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

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

Це допоможе, коли вам потрібно запустити тести з коду, оскільки він не має залежності від Maven чи будь-яких інших інструментів управління побудовою.

Зауважте, що це буде запускати всі тестові випадки паралельно, якщо у вас є залежність між різними тестовими випадками, це може призвести до помилкових позитивних результатів. У вас НЕ БУДЕ НЕ мати взаємозалежних тестів.


0

Ще один вибір: Punner, новий паралельний junit runner та 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 Framework, дрібнозернисте блокування, обслуговування журналів, розподілений механізм робочого процесу тощо. Це заощадило багато мого часу очікування.

Punner ще не підтримує деяку розширену функцію. Я дуже радий, якщо ви могли б спробувати і дати мені відгуки.


-3

Ви можете змінити свій тест на тест TestNg за хвилину (просто потрібно змінити імпорт), TestNG - найкращий при паралельному тестуванні.


-3

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


1
Я випробував рішення GridGain і у мене були дві основні проблеми. По-перше, ви повинні сказати GridGain виключити зі свого класового завдання сітки все, що також використовує GridGain, наприклад, Spring та багато матеріалів Apache Commons. По-друге, мережеве навантаження класів, хоча геніальна ідея, не працює для бібліотек, які хочуть шукати шлях по класу, наприклад, Spring
Graham Lea,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.