Статьи

Категоризация тестов для сокращения времени сборки

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

Модульные тесты

Модульные тесты — это небольшие тесты (тесты для одного варианта использования или модуля), выполняемые в памяти (не взаимодействующие с базой данных, очередями сообщений и т. Д.), Повторяемые и быстрые. Для нашего разговора давайте ограничимся тестовыми примерами на основе JUnit, которые разработчики пишут для проверки своего отдельного фрагмента кода.

Интеграционные тесты

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

Почему эта дифференциация важна?

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

Как именно эта гибкость помогает?

  1. Разработчики строят чаще. Это — в Agile мире означает — разработчики запускают модульные тесты чаще (часто несколько раз в день).
  2. Разработчики быстрее узнают об ошибке и тратят меньше времени на кодирование сломанной кодовой базы. Это означает экономию времени и денег.
  3. Исправлять ошибки проще и быстрее. Учитывая частоту сборок, можно было бы зафиксировать меньшее количество «нарушающего кода», и, следовательно, легче обнулить ошибку и исправить ее.
  4. И последнее, но не менее важное: любой, кто занимался профессиональным кодированием, будет свидетельствовать о том, что, хотя иногда помогает сделать 10-минутный перерыв, ничто не убивает креативность кодера более эффективно, чем ожидание 1-часового построения. , Влияние на мораль неосязаемо, но огромно.

Как именно сбить время сборки?

Нет единого размера, который подходит всем (никогда не бывает). Точные выполняемые шаги для сокращения времени сборки и выпуска будут зависеть от многих переменных, включая технологический стек продукта (Java, DotNet, php), технологии сборки и выпуска (Batch-файлы, Ant, Maven) и многие другие.

Для комбинации Java, Maven и JUnit…

Давайте начнем с использования Maven для создания простого Java-приложения для демонстрации случая.

\ MavenCommands.bat

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
ECHO OFF
 
REM =============================
REM Set the env. variables.
REM =============================
SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.3\bin;
SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0
 
REM =============================
REM Create a simple java application.
REM =============================
call mvn archetype:create ^
  -DarchetypeGroupId=org.apache.maven.archetypes ^
  -DgroupId=org.academy ^
  -DartifactId=app001
pause

Если вы запустите этот пакетный файл, вы начнете со стандартного готового приложения Java.

Java-приложение по умолчанию не поставляется с последней версией JUnit. Возможно, вы захотите изменить конфигурацию Maven, чтобы добавить последнюю версию JUnit.

\ pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[...]
 
                     
                     4.10
                     
[...]
                     
 
                                                
 
                      
                      junit
                                 
 
                      
                      junit
                           
 
                      
                      ${junit.version}
                      
 
                      
                      test
                                      
 
                    

Теперь добавьте тестовый класс JUnit.

/app001/src/test/java/org/academy/AppTest.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public class AppTest {
 
private final static Logger logger = LoggerFactory.getLogger(AppTest.class);
 
@Test
public void smallAndFastUnitTest() {
 logger.debug("Quick unit test. It is not expected to interact with DB etc.");
 assertTrue(true);
}
 
@Test
@Category(IntegrationTest.class)
public void longAndSlowIntegrationTest() {
 logger.debug("Time consuming integration test. It is expected to interact with DB etc.");
 assertTrue(true);
}
}

Как вы могли заметить, есть маркер IntegrationTest.class. Вам также нужно будет создать этот класс.

/app001/src/test/java/org/academy/annotation/type/IntegrationTest.java

1
2
3
public interface IntegrationTest {
  // Just a marker interface.
}

Создание интерфейса маркера и аннотирование ваших тестовых методов (или классов, если вы захотите) — это все, что вам нужно сделать в своем коде.

Теперь все, что остается сделать, — это сказать Maven, чтобы он выполнял «интеграционные тесты» только на этапе интеграционных тестов. Это означает, что разработчик может в большинстве случаев запускать только модульные тесты (быстрые, которые изолированы от баз данных, очередей и т. Д.). Сервер Continuous Integration, т.е. Hudson (или ему подобные), будет запускать модульные тесты и интеграционные тесты (которые будут медленнее, так как ожидается, что они будут взаимодействовать с базами данных и т. Д.), И это может произойти в одночасье.

Итак, вот как вы это делаете.

/pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
                                                                           
 
 
org.apache.maven.plugins
                                     
 
 
maven-surefire-plugin
                                  
 
 
2.12
                                                         
 
                                                                  
 
                                                                 
 
  
  org.apache.maven.surefire
                              
 
  
  surefire-junit47
                                 
 
  
  2.12
                                                   
 
                                                                
 
                                                                 
 
                                                                 
 
 
 -XX:-UseSplitVerifier
                                 
 
 
 org.academy.annotation.type.IntegrationTest
 
 
                                                                
 
      

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

1
mvn clean test

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

Для тестирования интеграции добавьте следующее.

/pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
                                                           
 
 
maven-failsafe-plugin
                  
 
 
2.12
                                         
 
                                                  
 
                                                 
 
  
  org.apache.maven.surefire
              
 
  
  surefire-junit47
                 
 
  
  2.12
                                   
 
                                                
 
                                                 
 
                                                 
 
 
 org.academy.annotation.type.IntegrationTest
 
 
                                                
 
                                                    
 
                                                  
 
                                                   
 
   
   integration-test
                          
 
                                                  
 
                                           
 
                                             
 
    
    **/*.class
                       
 
                                            
 
                                          
 
                                                 
 
                                                  

Это означает, что Hudson или разработчик (если он выберет) может запустить все тесты, модуль и интеграцию одной командой.

1
mvn clean verify   

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

1
mvn clean deploy

Вот и все. Вы сделали один шаг к более быстрой сборке и более гибкому способу работы. Удачного кодирования.

дальнейшее чтение

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

Ссылка: категоризируйте тесты, чтобы сократить время сборки. от нашего партнера JCG Partho в блоге Tech for Enterprise .