TestContainers + JUnit 5 = elegant integration and e2e tests for microservices

TestContainers + JUnit 5 = elegant integration and e2e tests for microservices

Fd8ac25831e3e9cc7d70944c77a369ef?s=128

Nikolay Kuznetsov

November 07, 2019
Tweet

Transcript

  1. TestContainers + JUnit 5 = elegant integration and e2e tests

    for microservices Nikolay Kuznetsov @nikolayk812 TESTING UNITED Vienna, 7 November 2019
  2. About me • Go developer at Zalando Helsinki • Java

    developer at Infobip, DevExperts • C developer at Samsung, Motorola
  3. My testing experience • Unit, integration and end-to-end automated tests

    development • Various organizational structures ◦ Separate QA teams ◦ QA engineers in a dev team ◦ No QA teams/engineers at all
  4. Key points • Targeting automated testing • Examples and demos

    in Java: TestContainers-Java, JUnit 5, Spring Boot • Principles are language-agnostic
  5. Why integration testing?

  6. 2 unit tests, 0 integration tests

  7. Tests trade-offs

  8. None
  9. Basic integration test

  10. Integration testing evolution • In-memory mocking • Local DBs •

    Vagrant • Docker, Docker Compose • Docker API
  11. Docker architecture

  12. How to start a container for test? • Shell scripts

    • Maven plugin • Docker Compose • Docker API • MiniKube, Kubernetes
  13. Shell scripts

  14. Maven plugin github.com/fabric8io/docker-maven-plugin

  15. Docker Compose

  16. Docker API

  17. None
  18. TestContainers flavors

  19. TestContainers Java • github.com/testcontainers/testcontainers-java • Wraps docker-java library • Docker

    environment autodiscovery • Host port randomization • Containers clean up on JVM shutdown • Readiness waiting strategies
  20. As simple as var redis = new GenericContainer("redis:5.0.5") .withExposedPorts(6379); var

    postgres = new PostgreSQLContainer();
  21. Docker environment autodiscovery

  22. Host port randomization • Prevents port conflicts • Enables parallel

    CI builds • API to get an actual host port
  23. Containers cleanup github.com/testcontainers/moby-ryuk

  24. Readiness waiting strategies • Host port • HTTP status/body •

    Log message • Docker healthcheck • Combination of above • Custom
  25. Demo setup User Service

  26. Demo scenario User Service INSERT INTO SELECT FROM

  27. Demo github.com/nikolayk812/tu-tc-demo

  28. Demo recap • JUnit 5 integration via Extension API ◦

    @TestContainers / @Container • TestContainers Modules ◦ 14 databases ◦ Kafka, MockServer, LocalStack, ToxiProxy, etc
  29. JUnit 5 Extensions • Customizable extension points: ◦ Life-cycle phases

    ◦ Parameter resolution ◦ Conditional execution, etc • Extension logic registered with @ExtendsWith
  30. github.com/nikolayk812/tu-tc-demo Demo-2: setup User Service

  31. Demo-2: scenario User Service POST /users GET /user/<id>

  32. Demo-2: Docker network User Service user-alias: 8083 postgres-alias: 5432 localhost:

    32812
  33. Demo 2 github.com/nikolayk812/tu-tc-demo

  34. Demo-2: recap • Docker network and alias

  35. Why end-to-end testing? • Business flows across multiple services •

    Regression, when ◦ + new service ◦ - legacy service
  36. Testing/staging deployed cluster Spring Cloud Kubernetes

  37. Testing against a deployed cluster • Deploy a new service

    version to the cluster? • Unexpected versions of dependent services • Unexpected database states ◦ Care to clear after the test? • Parallel CI builds?
  38. On-demand cluster for E2E tests + Locally and at CI

    machines + Control over dependent services versions - Time to start all containers - Resources: memory and CPU How to do it?
  39. Kubernetes for E2E tests?

  40. Kubernetes for E2E tests - YAGNI TestContainers + Docker network!

  41. E2E test setup User Service Item Service

  42. Takeaways • https://testcontainers.org • Balance between flexibility, speed and features

    • Works on Mac, Linux, Windows
  43. QUESTIONS ?