Недавно мой коллега наткнулся на Pact.io. Наше текущее приложение выросло до более чем 50 сервисов, и мы начинаем испытывать некоторые сбои интеграционных тестов и хрупкую среду разработки / принятия. Поэтому мы решили взглянуть на способы помочь с этим.
Я начал с чтения: https://docs.pact.io/faq/convinceme.html
Тогда смотрите: https://www.youtube.com/watch?v=-6x6XBDf9sQ&feature=youtu.be
Эти 2 ресурса убедили меня дать ему шанс.
Поэтому я разработал и создал быстрый набор загрузочных приложений Spring, репозиторий GitHub, чтобы проверить концепции и заставить все работать.
Чтобы выделить некоторые важные моменты из демонстрации.
Потребитель:
Pact — это ориентированная на потребителя среда тестирования. Здесь вы определяете модульный тест, который проверяет ответ http-сервера, и вы утверждаете против этого.
Как только тест пройден успешно, он создает pact-файл json в каталоге / pacts.
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
|
public class TestProvider { @Rule public PactProviderRule provider = new PactProviderRule( "test_provider" , "localhost" , 8081 , this ); @Pact (state = "default" , provider = "test_provider" , consumer = "test_consumer" ) public PactFragment createFragment(PactDslWithProvider builder) { Map<String, String> headers = new HashMap<>(); headers.put( "content-type" , "application/json" ); return builder .given( "default" ) .uponReceiving( "Test User Service" ) .path( "/user/1" ) .method( "GET" ) .willRespondWith() .status( 200 ) .headers(headers) .body( "{" + " \"userName\": \"Bob\",\n" + " \"userId\": \"1\",\n" + " \"firstName\": null,\n" + " \"lastName\": null,\n" + " \"email\": null,\n" + " \"groups\": null\n" + "}" ) .toFragment(); } @Test @PactVerification ( "test_provider" ) public void runTest() throws IOException { final RestTemplate call = new RestTemplate(); final User expectedResponse = new User(); expectedResponse.setUserName( "Bob" ); expectedResponse.setUserId( "1" ); final User forEntity = call.getForObject(provider.getConfig().url() + "/user/1" , User. class ); assertThat(forEntity, sameBeanAs(expectedResponse)); } } |
Таким образом, после запуска теста «mock» и создания файла pact. Вам необходимо включить плагин maven… pact…, который затем используется для публикации содержимого папки / пакта посреднику pact…, который определен в pom, как показано ниже.
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
|
< dependencies > < dependency > < groupId >au.com.dius</ groupId > < artifactId >pact-jvm-consumer-junit_2.11</ artifactId > < version >3.3.6</ version > < scope >test</ scope > </ dependency > </ dependencies > < build > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-surefire-plugin</ artifactId > < version >2.18</ version > < configuration > < systemPropertyVariables > < pact.rootDir >pacts</ pact.rootDir > < buildDirectory >${project.build.directory}</ buildDirectory > </ systemPropertyVariables > </ configuration > </ plugin > < plugin > < groupId >au.com.dius</ groupId > < artifactId >pact-jvm-provider-maven_2.11</ artifactId > < version >3.3.4</ version > < configuration > < pactDirectory >pacts</ pactDirectory > < projectVersion >1.0.1</ projectVersion > </ configuration > </ plugin > </ plugins > </ build > |
Режиссер:
При этом используется интеграция JUnit из Pact.io для загрузки пактов от брокера и последующего запуска с работающей службой.
Так как здесь уже используется аннотация @RunWith, я не смог использовать бегун с пружинной загрузкой. Таким образом, чтобы обойти это как шаг перед классом, я запускаю загрузочное приложение Spring, затем пакты запускаются для этого запущенного экземпляра … и загрузочное приложение снова останавливается после тестов. В зависимости от вашего варианта использования, я думаю, что это также будет возможность сделать это с @Before, чтобы вы запускали новый экземпляр службы перед каждым пакетом, но это сильно замедляло бы выполнение.
Аннотация @State позволяет клиентам определять определенное состояние, которое производитель может использовать для настройки дополнительных данных / условий, необходимых для выполнения теста.
После того, как договоры выполнены со службой, в целевой папке создаются отчеты.
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
|
@RunWith (PactRunner. class ) @Provider ( "test_provider" ) @PactBroker (host = "localhost" , port = "80" ) @VerificationReports ({ "console" , "markdown" }) public class TestPacts { private static ConfigurableApplicationContext application; @TestTarget public final Target target = new HttpTarget( 8080 ); @BeforeClass public static void startSpring(){ application = SpringApplication.run(ProviderServiceApplication. class ); } @State ( "default" ) public void toDefaultState() { System.out.println( "Now service in default state" ); } @State ( "extra" ) public void toExtraState() { System.out.println( "Now service in extra state" ); } @AfterClass public static void kill(){ application.stop(); } } |
Настройка Pact Broker
1. Получите общедоступные изображения из Docker Hub.
1
2
|
docker pull dius/pact_broker docker pull postgres |
2. Затем настройте Postgres DB
1
2
3
4
5
|
docker run --name pactbroker-db -e POSTGRES_PASSWORD=ThePostgresPassword -e POSTGRES_USER=admin -d postgres docker run -it --link pactbroker-db:postgres --rm postgres psql -h postgres -U admin CREATE USER pactbrokeruser WITH PASSWORD 'TheUserPassword' ; CREATE DATABASE pactbroker WITH OWNER pactbrokeruser; GRANT ALL PRIVILEGES ON DATABASE pactbroker TO pactbrokeruser; |
3. После запуска БД запустите реальный брокер:
1
|
docker run --name pactbroker --link pactbroker-db:postgres -e PACT_BROKER_DATABASE_USERNAME=pactbrokeruser -e PACT_BROKER_DATABASE_PASSWORD=TheUserPassword -e PACT_BROKER_DATABASE_HOST=postgres -e PACT_BROKER_DATABASE_NAME=pactbroker -d -p 80 : 80 dius/pact_broker |
Дополнительные ссылки:
- https://docs.pact.io/documentation/
- https://docs.pact.io/documentation/sharings_pacts.html
- https://github.com/DiUS/pact-jvm
- https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-junit
Получить пример проекта
Ссылка: | Тестирование, ориентированное на потребителя, с помощью Pact & Spring Boot от нашего партнера JCG Брайана Дю Приза в блоге Zen, посвященном искусству ИТ . |