Integration testing with TestСontainers-Go
如果无法正常显示,请先停止浏览器的去广告插件。
相关话题:
#zalando
1. Integration testing with
TestСontainers-Go
Erdem Toraman
Nikolay Kuznetsov
GoDays - Berlin
23 Jan 2020
2. About us
● Go developers at Zalando in Helsinki
● Project with ~20 microservices in Go
● User perspective of TestContainers-Go library
3. 2 unit tests passed, 0 integration tests
4. Basic integration test
5. Getting a database for testing
● Local database
● In-memory mock
● Docker!
6. Docker advantages
● 100% compatible databases
● Same version as production
● Empty DB state
7. Integration testing with Docker
8. Easy-peasy!
docker run -d -p 5432:5432 postgres:12.1
9. What could go wrong?
● Host port conflicts
● Not ready сontainer / service
● Resource leak (the container keeps running)
● Stale data (if reusing the same container)
● Starting mechanism both for CI and a local machine
10. Solving some issues
11.
12. Docker API
docs.docker.com/engine/api/latest
13. Exec example
14.
15. TestContainers flavors
16. TestContainers-Go
github.com/testcontainers/testcontainers-go
● Docker Go client under the hood
● Host port randomization
● Containers clean up at the test shutdown
● Readiness waiting strategies
17. As simple as
pgContainer, err := tc.GenericContainer(ctx,
tc.GenericContainerRequest{
ContainerRequest: tc.ContainerRequest{
Image:
"postgres:12.1",
ExposedPorts: []string{"5432/tcp"},
},
})
18. Host port randomization
● API to get a host port:
port, err := pgContainer.MappedPort(ctx, "5432/tcp")
● Prevents port conflicts
● Enables parallel builds
19. Containers cleanup: Ryuk
github.com/testcontainers/moby-ryuk
● Ryuk kills containers (networks, volumes) by labels
● TC assigns labels to started containers
● TC keeps a connection to Ryuk open
20. Waiting strategies
● Host port
● HTTP
● Logs
● Custom
● Multi
21. Host port waiting strategy
tc.ContainerRequest{
Image:
"postgres:12.1",
ExposedPorts: []string{"5432/tcp"},
WaitingFor: wait.ForListeningPort("5432/tcp"),
},
● Default (customizable) timeout is 60 seconds
● Impl checks both from outside and inside container
22. HTTP waiting strategy
WaitingFor: wait.ForHTTP("/health").
WithPort("8080/tcp").
WithStatusCodeMatcher(
func(status int) bool { return status == http.StatusOK }),
23. Demo
24. Demo I: integration testing
github.com/erdemtoraman/godays-testcontainers-demo
● Testing interaction with a database
● Create and Get users from Postgres
User Repository
25. What happened?
● Ran a Postgres container
● Mapped a random port to the host machine
● Ran tests against it
● Cleaned up the containers
26. Demo II: end-to-end testing
github.com/erdemtoraman/godays-testcontainers-demo
Docker Network
Ticket Service
HTTP
User Service
Tests
27. Takeaways
● testcontainers.org
● Balance between flexibility, speed and features
● Great for integration tests
● Possible to use for end-to-end tests
28. Thank you!
@erdem_toraman, @nikolayk812
erdemtoraman