33
Reproducible component tests for microservices using Docker Pavel Rabetski

Reproducible component tests using docker

Embed Size (px)

Citation preview

Page 1: Reproducible component tests using docker

Reproducible component tests for microservices using Docker

Pavel Rabetski

Page 2: Reproducible component tests using docker

Component tests

● Verify behaviour of a component

● Cheaper to maintain than system tests

● Easier to locate problems compared to system tests

Page 3: Reproducible component tests using docker

Monolithic app vs Micro Services

Monolithic appMS1

MS3

MS2

MS4

● same lifecycle● same runtime/environment● component is a “grey box”

● different lifecycle● different runtime/environment● component is a “black box”

Page 4: Reproducible component tests using docker

Component tests

Test script MS

Test env

Page 5: Reproducible component tests using docker

Component tests

S0 S1T1:

S0 S2T2:

S0 S3T3:

Test script

Page 6: Reproducible component tests using docker

Component tests: tests in sequence

S0 S1T1:

S1 ?T2:

Page 7: Reproducible component tests using docker

Component tests: repeat same test

S0 S3T3:

S3 ?T3:

Page 8: Reproducible component tests using docker

Approach 1: cleanup/reset state

S0 S1T1:

S1 S0T1 cleanup:

S0 S2T2:

S2 S0T2 cleanup:

Extra development effort: keep track of changes and add cleanup code

Not always possible: e.g. deleting an entity just marks delete property = true

Page 9: Reproducible component tests using docker

Approach 2: separate contexts

Sx SnTn:UserId=n

S0 S1T1:UserId=1

Extra development effort: keep track of the unique context

Not always possible: if we have a global resource or complex pre-generated data

S1 S2T2:UserId=2

Page 10: Reproducible component tests using docker

Alternative approach: recreate test environment

Test script

Less development effort: no need to separate contexts or clean up after test

No constraints from previous methods: possible with global resource or pre-generated data

MS

Test env

MS

Test env

MS

Test env

Page 11: Reproducible component tests using docker

Alternative approach: recreate test environment

Monolithic app

Page 12: Reproducible component tests using docker

Alternative approach: recreate test environment

Monolithic app

Page 13: Reproducible component tests using docker

Alternative approach: recreate test environment

Monolithic app

MS

Page 14: Reproducible component tests using docker

pavradev/dockerbayApache 2.0

It is Java library for component testingIt does orchestrate docker environmentIt uses JUnit and Docker Java Client

Page 15: Reproducible component tests using docker

Example: Hotel booking web app

webapp

db

service webapp

db service

Page 16: Reproducible component tests using docker

Maven dependency

<dependency> <groupId>com.github.pavradev</groupId> <artifactId>dockerbay</artifactId> <version>${dockerbay.version}</version> <scope>test</scope></dependency>

Page 17: Reproducible component tests using docker

Configuring dockerbay: JUnit Rule

@Rulepublic DockerRule dockerRule = DockerRule.getDefault() .addContainer(postgresContainer) .addContainer(reviewsMockContainer) .addContainer(webappContainer);

Page 18: Reproducible component tests using docker

Configuring dockerbay: db container

private ContainerConfig postgresContainer = ContainerConfig.builder() .withImage("postgres:9") .withName("postgres") .waitForLogEntry("database system is ready to accept connections") .build();

Page 19: Reproducible component tests using docker

Configuring dockerbay: webapp container

private ContainerConfig webapp = ContainerConfig.builder() .withImage("demo/webapp") .withName("webapp") .waitForUrl("/api/hotels") .withExposedTcpPort(8082) .build();

Page 20: Reproducible component tests using docker

Configuring dockerbay: service container

private ContainerConfig reviewsMockContainer = ContainerConfig.builder() .withImage("ekino/wiremock:2.1.11") .withName("reviews-mock") .withExposedTcpPort(8083) .withCmd(Arrays.asList("--port", "8083", "--verbose")) .build();

Page 21: Reproducible component tests using docker

Add tests

public class WebappCT {@Testpublic void shouldGetHotelWithReviews() { ...}@Testpublic void shouldUpdateHotel() { ...}@Testpublic void shouldDeleteHotel() { ...}}

Page 22: Reproducible component tests using docker

Add tests@Testpublic void shouldUpdateHotel() { //create dummy hotel reqSpec.contentType(ContentType.JSON) .body("{\"name\":\"Dummy hotel\",\"address\":\"Dummy address\",\"zip\":\"4001\"}") .post("/api/hotels"); //update dummy hotel address reqSpec.contentType(ContentType.JSON) .body("{\"address\":\"Updated address\",\"zip\":\"4004\"}") .put("/api/hotels/1"); //validate address updated reqSpec.get("/api/hotels/1") .then() .assertThat() .body("address", equalTo("Updated address"));}

Page 23: Reproducible component tests using docker

Add tests@Testpublic void shouldGetHotelWithReviews() { //create dummy hotel reqSpec.contentType(ContentType.JSON) .body("{\"name\":\"Dummy hotel\",\"address\":\"Dummy address\",\"zip\":\"4001\"}") .post("/api/hotels"); //mock GET request for hotel reviews reviewsMock.register(get(urlEqualTo("/api/reviews?hotelId=1")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("[...]"))); //validate dummy hotel returned with reviews reqSpec.get("/api/hotels/1") .then().assertThat() .statusCode(200) .and().body("name", equalTo("Dummy hotel")) .and().body("reviews.size()", equalTo(1));}

Page 24: Reproducible component tests using docker

Execute

dockerbay

DOCKER_HOST

Page 25: Reproducible component tests using docker

Execute

pull images

DOCKER_HOST

WM

Page 26: Reproducible component tests using docker

Execute

pull images

create custom network

DOCKER_HOST

WM

{id}

Page 27: Reproducible component tests using docker

Execute

pull images

create custom network

create and start containers

DOCKER_HOST

WM

{id}

webapp

db service

{id}-webapp {id}-db {id}-service

Page 28: Reproducible component tests using docker

Execute

pull images

create custom network

create and start containers

execute test

DOCKER_HOST

WM

{id}

webapp

db service

{id}-webapp {id}-db {id}-service

Page 29: Reproducible component tests using docker

Execute

pull images

create custom network

create and start containers

stop and remove containers

execute test

DOCKER_HOST

WM

{id}

Page 30: Reproducible component tests using docker

Execute

pull images

create custom network

create and start containers

stop and remove containers

execute test

remove custom network

DOCKER_HOST

WM

Page 31: Reproducible component tests using docker

Parallelization

T1

T2

T3

Test script

Page 32: Reproducible component tests using docker

Parallelization

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <configuration> <parallel>all</parallel> <threadCount>3</threadCount> <perCoreThreadCount>false</perCoreThreadCount> </configuration></plugin>

Page 33: Reproducible component tests using docker

Questions