Junit: тест интеграции интеграции и модульные тесты

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

Итак, я пытаюсь придумать способ их разделить, так что после этого я смогу запустить unit test хороший и быстрый, а затем интеграционные тесты.

Параметры:..

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

  • Переместитесь в Junit4 (из версии 3) и добавьте в аннотацию классы для их разделения.

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

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

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

1: Кажется, это самое опрятное решение, но моя кишка говорит, что там должно быть лучшее решение.

Итак, это мой вопрос, как вы много разбираетесь в интеграционных тестах и ​​правильных модульных тестах?

Ответ 1

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

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

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

Ответ 2

Вы можете легко разбить их, используя категории 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

Красота этого решения заключается в том, что ничего не меняется для сторон unit test.

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

Настройка тестов интеграции 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>

Если вы переносите это в профиль с id 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.

Ответ 3

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

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

Ответ 4

Я бы подошел к Junit4 только для его использования.

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

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

Ответ 5

Использование IfProfileValue spring аннотация позволяет достичь этого без плагина или конфигурации 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 будет работать только unit test. Добавьте аргументы -Dtest-groups=integration в виртуальную машину, чтобы выполнить как интеграционные, так и модульные тесты.

Ответ 6

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

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

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