it-swarm.com.ru

Junit: расщепление интеграционного теста и юнит-тесты

Я унаследовал нагрузку теста Junit, но эти тесты (кроме большинства не работающих) представляют собой смесь реальных модульных тестов и интеграционных тестов (требующих внешних систем, БД и т.д.).

Поэтому я пытаюсь придумать, как на самом деле отделить их, чтобы я мог быстро и быстро запустить модульное тестирование, а затем интеграционные тесты.

Варианты ..

  1. Разделите их на отдельные каталоги.

  2. Перейдите к Junit4 (из v3) и аннотируйте классы, чтобы разделить их.

  3. Используйте соглашение об именовании файлов, чтобы сказать, что такое класс, то есть AdapterATest и AdapterAIntergrationTest.

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

2: рискует, что разработчики могут начать писать интеграционные тесты в классах модульных тестов, и это просто становится грязным.

1: Похоже, самое лучшее решение, но моя интуиция говорит, что там должно быть лучшее решение.

Так что это мой вопрос, как вы разбиваете интеграционные тесты и правильные юнит-тесты?

119
jeff porter

В настоящее время я использую отдельные каталоги из-за организационной политики (и унаследованной от Junit 3), но теперь я перехожу к аннотациям, теперь я нахожусь на Junit 4.

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

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

10
Steven Mackenzie

Вы можете очень легко разделить их, используя категории JUnit и Maven.

Это очень и очень кратко показано ниже при тестировании модуля разделения и интеграции.

Определить интерфейс маркера

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

public interface IntegrationTest {}

Отметьте свои тестовые классы

Добавьте аннотацию категории в начало вашего тестового класса. Требуется имя вашего нового интерфейса.

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

Настройка модульных тестов Maven

Мы просто добавляем некоторые настройки в плагин 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 clean test, будут выполняться только ваши немаркированные юнит-тесты.

Настроить интеграционные тесты 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, поскольку это должен быть интерфейс на пути к классам (Maven проверит это).

Заметки:

  • Зависимость от surefire-junit47 необходима только тогда, когда Maven не переключается на бегун JUnit 4 автоматически. Использование элемента groups или excludedGroups должно инициировать переключение. см. Здесь .
  • Большая часть кода выше была взята из документации для плагина Maven Failsafe. См. Раздел "Использование категорий JUnit" на этой странице .
  • Во время моих тестов я обнаружил, что это работает, даже когда вы используете аннотации @RunWith() для запуска комплектов или тестов на основе Spring.
135
John Dobie

Мы используем Maven Surefire Plugin для запуска модульных тестов и Maven Failsafe Plugin для запуска интеграционных тестов. Модульные тесты следуют соглашениям об именах **/Test*.Java **/*Test.Java **/*TestCase.Java, интеграционные тесты - **/IT*.Java **/*IT.Java **/*ITCase.Java. Так что это на самом деле ваш вариант номер три.

В нескольких проектах мы используем TestNG и определяем разные группы тестов для интеграции/модульных тестов, но это, вероятно, вам не подходит.

37
lexicore

Я бы перешел на Junit4 только для того, чтобы иметь его :)

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

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

12
Janusz

Использование IfProfileValue пружинной аннотации позволяет достичь этого без дополнительного модуля или конфигурации maven.

Аннотируйте классы или методы тестов интеграции с помощью 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 для запуска как интеграции, так и модульных тестов.

8
Mit Mehta

Там не один правильный ответ. Как вы объяснили, есть несколько способов сделать это, которые будут работать. Я сделал и схему именования файлов, и разбил вещи на разные каталоги.

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

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

6
ndp