Junit: роздільний тест інтеграції та тести Unit


126

Я успадкував набір тесту Junit, але ці тести (крім більшості не працюючих) є сумішшю фактичних тестових одиниць та інтеграційних тестів (вимагають зовнішніх систем, db тощо).

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

Варіанти є ..

  1. Розділіть їх на окремі каталоги.

  2. Перейдіть до Junit4 (від v3) та помічте класи, щоб розділити їх.

  3. Використовуйте умову іменування файлів, щоб сказати, що таке клас, тобто AdapterATest та AdapterAIntergrationTest.

3 має місце питання, що Eclipse має можливість "Запустити всі тести у вибраному проекті / пакеті або папці". Тому було б дуже важко просто запустити інтеграційні тести.

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

1: Схоже, найновіше рішення, але моя кишка каже, що там повинно бути краще рішення.

Отже, це моє питання, як ви багато розбиваєте інтеграційні тести та належні тестові одиниці?


Я просто хотів би подякувати всім за ваш внесок, я знаю, що це суб’єктивне запитання, і немає однозначної відповіді. Але ви допомогли мені зрозуміти, що немає інших варіантів, ніж ті, які я перерахував. Я думаю, що я зараз перейду зі структурою каталогу і перейду до JUnit4, хоча поки не використовую анотації для їх розбиття.
jeff porter

Відповіді:


10

Наразі я використовую окремі каталоги завдяки організаційній політиці (і спадщині 3 червня), але зараз я прагну перейти до анотацій. Зараз я перебуваю на 4 червня.

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

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


145

Ви можете розділити їх дуже легко, використовуючи категорії JUnit та Maven.

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

Визначте інтерфейс маркера

Перший крок у групуванні тесту за допомогою категорій - це створення інтерфейсу маркера.

Цей інтерфейс буде використовуватися для позначення всіх тестів, які потрібно запустити як інтеграційні тести.

public interface IntegrationTest {}

Позначте свої тестові класи

Додайте примітку до категорії у верхній частині свого тестового класу. Він приймає назву вашого нового інтерфейсу.

import org.junit.experimental.categories.Category;
@Category(IntegrationTest.class)
public class ExampleIntegrationTest{
  @Test
  public void longRunningServiceTest() throws Exception {
  }
}

Налаштування тестів Maven Unit

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

Ми просто додаємо деяку конфігурацію до плагіна Maven surefire, щоб змусити ігнорувати будь-які тести інтеграції.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <includes>
      <include>**/*.class</include>
    </includes>
    <excludedGroups>com.test.annotation.type.IntegrationTest</excludedGroups>
  </configuration>
</plugin>

Коли ви робите тест на чисту mvn, запускаються лише ваші тести без маркування.

Налаштувати тести інтеграції Maven

Знову конфігурація для цього дуже проста.

Щоб запустити лише тести інтеграції, використовуйте це:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <groups>com.test.annotation.type.IntegrationTest</groups>
  </configuration>
</plugin>

Якщо ви загорнули це у профіль із ідентифікатором IT, ви можете запускати лише швидкі тести, використовуючи mvn clean install. Для запуску просто інтеграції / повільних тестів використовуйте mvn clean install -P IT.

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

<profiles>
    <profile>
        <id>IT</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <excludedGroups>java.io.Serializable</excludedGroups> <!-- An empty element doesn't overwrite, so I'm using an interface here which no one will ever use -->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Як бачите, я виключаю тести, на які позначено пояснення java.io.Serializable. Це необхідно, тому що профіль успадкує конфігурацію за замовчуванням плагіна Surefire, тому навіть якщо ви скажете <excludedGroups/>або <excludedGroups></excludedGroups>, це значення com.test.annotation.type.IntegrationTestбуде використано.

Ви також не можете використовувати, noneоскільки це повинен бути інтерфейс на classpath (Maven перевірить це).

Примітки:

  • Залежність до surefire-junit47цього потрібна лише тоді, коли Maven не перемикається автоматично на бігун JUnit 4. Використання groupsабо excludedGroupsелемент повинен викликати перемикач. Дивіться тут .
  • Більшість наведених вище кодів було взято з документації на плагін Maven Failsafe. Дивіться розділ "Використання категорій JUnit" на цій сторінці .
  • Під час моїх тестів я виявив, що це працює навіть тоді, коли ви використовуєте @RunWith()примітки для запуску наборів або тестів на основі Spring.

18
Я думаю, що у вашому останньому фрагменті pom.xml є помилка. ви вставили той самий фрагмент, що і для фази "тестування". він все ще виключає інтеграційні тести, а також не пов'язаний з будь-якою фазою фази.
Олексій

1
Дійсно, останній фрагмент пом - це помилка копіювання та вставки. Він повинен показувати плагін maven-failsafe.
Пауло Мерсон

2
Отже, яким повинен бути другий xml? : O
Лив

Вам не доведеться використовувати трюк (остання магія із Serializable), якщо ви використовуєте профіль Maven за замовчуванням
user831217

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

40

Ми використовуємо плагін Maven Surefire для запуску модульних тестів, а плагін Maven Failsafe - для запуску інтеграційних тестів. Одиничні тести відповідають **/Test*.java **/*Test.java **/*TestCase.javaумовам іменування, інтеграційні тести - **/IT*.java **/*IT.java **/*ITCase.java. Тож насправді ваш варіант номер три.

У кількох проектах ми використовуємо TestNG та визначаємо різні тестові групи для інтеграції / тестування одиниць, але це, мабуть, не підходить для вас.


1
+1 для Maven + surefire + failsafe + jubo комбо. Я не здогадувався, що програвання "IT *" буде запускатися автоматично. Солодке.
PapaFreud

13

Я хотів би перейти на Junit4 тільки для того, щоб мати його :)

Ви можете розділити їх на різні тестові набори. Я не знаю, як вони організовані в Junit3, але в Junit4 повинно бути просто створити тестові набори і помістити всі реальні тести одиниці в один з них, а потім використовувати другий набір для інтеграційних тестів.

Тепер визначте конфігурацію запуску для обох пакетів у затемненні, і ви можете легко запустити один набір. Ці пакети також можуть бути запущені з автоматизованого процесу, що дозволяє запускати одиничні тести кожного разу, коли джерело змінюється, а можливо, тести інтеграції (якщо вони дійсно великі) лише раз на день або раз на годину.


9

Використання весняної анотації IfProfileValue дозволяє досягти цього без необхідного додатка або конфігурації.

Анотуйте тестові класи інтеграції або методи, використовуючи IfProfileValue

import org.springframework.test.annotation.IfProfileValue;

@IfProfileValue(name="test-groups", value="integration")
public class ExampleIntegrationTest{
    @Test
    public void longRunningServiceTest() throws Exception {
    }
} 

Щоб запустити лише тестові одиниці:

mvn clean test

Для запуску за допомогою тесту інтеграції та тестування блоків:

mvn clean test -Dtest-groups=integration

Крім того, "Запустити всі тести" в IDE буде виконувати тільки тестовий блок. Додайте -Dtest-groups=integrationдо аргументів VM, щоб запустити як інтеграційні, так і одиничні тести.


Цей підхід є приємним і простим, але я вважаю, що за замовчуванням я хотів би запустити всі тести (включаючи тести інтеграції). Це неможливо при такому підході, чи не так?
csalazar

6

Немає однієї правильної відповіді. Як ви пояснили, існує кілька способів зробити це, який буде працювати. Я зробив як схему іменування файлів, так і розділив речі на різні каталоги.

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.