BDD-тестирование веб-сервиса при помощи JBehave и Docker

от автора

Целью данной статьи является демонстрация возможности BDD-тестирования веб-сервиса с использованием Docker и JBehave

Весь исходный код приведен здесь

Подготовка

Ставим Docker, но до этого — разрешаем использование виртуализации в BIOS, в Windows — устанавливаем ее дополнительные компоненты: Hyper-V, и апдейтим ее до версии, которую просит Docker.

Структура приложения

Приложение представляет собой мультимодульное maven-приложение, со следующими модулями:

  • spring-boot-empty-project — собственно spring-boot приложение
  • dockerization — модуль, оборачивающий spring-boot приложение в Docker-образ
  • jbehave-testing — модуль BDD-тестирования

Немного подробнее:

Сервис

Обычный spring-boot сервис, с контроллером, возвращающим «Hello World!» для домашней страницы:

@RestController public class Controller {      @RequestMapping("/")     @ResponseBody     String home() {         return "Hello World!";     } }

Оборачивание сервиса в Docker-образ

Тут используем docker-maven-plugin от Spotify и java:8u111-jre-alpine образ в качестве базового образа. Чтобы приложение стартовало после старта образа — используем секцию entryPoint конфигурации плагина:

<!-- *** Build images *** --> <execution>   <id>build-spring-boot-simple-app-image</id>   <phase>package</phase>   <goals> 	<goal>build</goal>   </goals>   <configuration> 	<imageName>jbehave-spring-boot-simple-app-image:${project.version}</imageName> 	<baseImage>java:8u111-jre-alpine</baseImage> 	<!-- run application when container start --> 	<entryPoint>["java", "-jar", "/spring-boot-empty-project-${project.version}.jar"]</entryPoint> 	<!-- copy the service's jar file from target into the root directory of the image --> 	<resources> 	  <resource> 	    <targetPath>/</targetPath> 	    <directory>${project.build.directory}/lib</directory> 	    <include>spring-boot-empty-project-${project.version}.jar</include> 	  </resource> 	</resources> </configuration> </execution> 

В той же фазе package тегаем созданный образ:

<!-- *** Tag images *** --> <execution>   <id>tag-spring-boot-simple-app-image</id>   <phase>package</phase>   <goals> 	<goal>tag</goal>   </goals>   <configuration>     <image>jbehave-spring-boot-simple-app-image:${project.version}</image>     <newName>${dockerRepository}/jbehave-spring-boot-simple-app-image:${project.version}</newName>   </configuration> </execution> 

В фазе push пушаем образ в репозиторий:

<!-- *** Push images *** --> <execution>   <id>push-spring-boot-simple-app-image</id>   <phase>deploy</phase>   <goals>     <goal>push</goal>   </goals>   <configuration>   <imageName>${dockerRepository}/jbehave-spring-boot-simple-app-image:${project.version}</imageName>   </configuration> </execution> 

Собственно BDD-тестирование

Описываем историю в story-файле:

Narrative: As a developer I want to get access to spring-boot application from outside of docker container  Scenario: After when Docker container with spring-boot app in it started, application home page is accessable  Then spring-boot application home page accessable 

— просто хотим, чтобы домашняя страница была доступна, чего же болей

В соответствии с именем story-файла создаем java-класс с именем GetAccessToSpringBootAppFromOutsideOfDockerContainer:

public class GetAccessToSpringBootAppFromOutsideOfDockerContainer extends JUnitStory {      // Here we specify the configuration, starting from default MostUsefulConfiguration, and changing only what is needed     @Override     public Configuration configuration() {         return new MostUsefulConfiguration()                 // where to find the stories                 .useStoryLoader(new LoadFromClasspath(this.getClass()))                 // CONSOLE and TXT reporting                 .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats().withFormats(Format.CONSOLE, Format.TXT));     }      // Here we specify the steps classes     @Override     public InjectableStepsFactory stepsFactory() {         // varargs, can have more that one steps classes         return new InstanceStepsFactory(configuration(), new CheckSpringBootAppHomePageAvailabilitySteps());     } }

В это классе используется другой класс, специфицирующий шаги тестирования:

public class GetAccessToSpringBootAppFromOutsideOfDockerContainer extends JUnitStory {      // Here we specify the configuration, starting from default MostUsefulConfiguration, and changing only what is needed     @Override     public Configuration configuration() {         return new MostUsefulConfiguration()                 // where to find the stories                 .useStoryLoader(new LoadFromClasspath(this.getClass()))                 // CONSOLE and TXT reporting                 .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats() .withFormats(Format.CONSOLE, Format.TXT));     }      // Here we specify the steps classes     @Override     public InjectableStepsFactory stepsFactory() {         // varargs, can have more that one steps classes         return new InstanceStepsFactory(configuration(), new CheckSpringBootAppHomePageAvailabilitySteps());     } }

Чтобы протестировать приготовленный Docker-образ с сервисом внутри — стартуем образ в фазе pre-integration-test и стопаем в фазе post-integration-test:

<!-- Hooking into the lifecycle --> <executions> 	<execution> 		<id>start</id> 		<phase>pre-integration-test</phase> 		<goals> 			<goal>start</goal> 		</goals> 	</execution> 	<execution> 		<id>stop</id> 		<phase>post-integration-test</phase> 		<goals> 			<goal>stop</goal> 		</goals> 	</execution> </executions> 

Также задаем таймаут для старта сервиса и префикс TC для отслеживания сообщений от Docker-образа в логах:

<!-- ............................................................... --> <!-- Runtime configuration for starting/stopping/linking containers --> <!-- ............................................................... --> <run>   <!-- Assign dynamically mapped ports to maven variables (which can be reused in integration tests) -->   <ports> 	<port>spring-boot-app.port:8090</port>   </ports> 	<wait> 	  <!-- Check for this URL to return a 200 return code .... --> 	  <url>                  http://${docker.host.address}:${spring-boot-app.port} 	  </url> 	  <!-- ... but at max 10 seconds --> 	  <time>10000</time> 	</wait> 	<log> 	  <prefix>TC</prefix> 	  <color>cyan</color> 	</log> </run> 

При запуске билда видим, что история тестируется успешно:

Running story stories/get_access_to_spring_boot_app_from_outside_of_docker_container.story  (stories/get_access_to_spring_boot_app_from_outside_of_docker_container.story) Scenario: After when Docker container with spring-boot app in it started, application home page is accessable ... Results :  Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

— собственно чего и хотелось бы.
ссылка на оригинал статьи https://habrahabr.ru/post/329034/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *