Skip to content

Commit 3db7d1c

Browse files
committed
feat(fxtestcontainer): provide module
1 parent bb9174d commit 3db7d1c

File tree

9 files changed

+740
-1
lines changed

9 files changed

+740
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: "fxtestcontainer-ci"
2+
3+
on:
4+
push:
5+
branches:
6+
- "feat**"
7+
- "fix**"
8+
- "hotfix**"
9+
- "chore**"
10+
paths:
11+
- "fxtestcontainer/**.go"
12+
- "fxtestcontainer/go.mod"
13+
- "fxtestcontainer/go.sum"
14+
pull_request:
15+
types:
16+
- opened
17+
- synchronize
18+
- reopened
19+
branches:
20+
- main
21+
paths:
22+
- "fxtestcontainer/**.go"
23+
- "fxtestcontainer/go.mod"
24+
- "fxtestcontainer/go.sum"
25+
26+
jobs:
27+
ci:
28+
uses: ./.github/workflows/common-ci.yml
29+
secrets: inherit
30+
with:
31+
module: "fxtestcontainer"

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
| [fxgcppubsub](fxgcppubsub) | Module for [GCP Pub/Sub](https://cloud.google.com/pubsub) |
1515
| [fxgomysqlserver](fxgomysqlserver) | Module for [Go Mysql Server](https://github.com/dolthub/go-mysql-server) |
1616
| [fxjsonapi](fxjsonapi) | Module for [JSON API](https://github.com/google/jsonapi) |
17-
| [fxslack](fxslack) | Module for [Slack](https://api.slack.com/) |
1817
| [fxredis](fxredis) | Module for [Redis](https://redis.io/docs/connect/clients/go/) |
18+
| [fxslack](fxslack) | Module for [Slack](https://api.slack.com/) |
19+
| [fxtestcontainer](fxtestcontainer) | Module for [Testcontainers](https://github.com/testcontainers/testcontainers-go) |
1920

2021
## Contributing
2122

fxtestcontainer/.golangci.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
run:
2+
timeout: 5m
3+
concurrency: 8
4+
5+
linters:
6+
enable:
7+
- asasalint
8+
- asciicheck
9+
- bidichk
10+
- bodyclose
11+
- containedctx
12+
- contextcheck
13+
- cyclop
14+
- decorder
15+
- dogsled
16+
- durationcheck
17+
- errcheck
18+
- errchkjson
19+
- errname
20+
- errorlint
21+
- exhaustive
22+
- forbidigo
23+
- forcetypeassert
24+
- gocognit
25+
- goconst
26+
- gocritic
27+
- gocyclo
28+
- godot
29+
- godox
30+
- gofmt
31+
- goheader
32+
- gomoddirectives
33+
- gomodguard
34+
- goprintffuncname
35+
- gosec
36+
- gosimple
37+
- govet
38+
- grouper
39+
- importas
40+
- ineffassign
41+
- interfacebloat
42+
- loggercheck
43+
- maintidx
44+
- makezero
45+
- misspell
46+
- nestif
47+
- nilerr
48+
- nilnil
49+
- nlreturn
50+
- nolintlint
51+
- nosprintfhostport
52+
- prealloc
53+
- predeclared
54+
- promlinter
55+
- reassign
56+
- staticcheck
57+
- tenv
58+
- thelper
59+
- tparallel
60+
- typecheck
61+
- unconvert
62+
- unparam
63+
- unused
64+
- usestdlibvars
65+
- whitespace

fxtestcontainer/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Yokai Test Container Module
2+
3+
[![ci](https://github.com/ankorstore/yokai-contrib/actions/workflows/fxtestcontainer-ci.yml/badge.svg)](https://github.com/ankorstore/yokai-contrib/actions/workflows/fxtestcontainer-ci.yml)
4+
[![go report](https://goreportcard.com/badge/github.com/ankorstore/yokai-contrib/fxtestcontainer)](https://goreportcard.com/report/github.com/ankorstore/yokai-contrib/fxtestcontainer)
5+
[![codecov](https://codecov.io/gh/ankorstore/yokai-contrib/graph/badge.svg?token=ghUBlFsjhR&flag=fxtestcontainer)](https://app.codecov.io/gh/ankorstore/yokai-contrib/tree/main/fxtestcontainer)
6+
[![Deps](https://img.shields.io/badge/osi-deps-blue)](https://deps.dev/go/github.com%2Fankorstore%2Fyokai-contrib%2Ffxtestcontainer)
7+
[![PkgGoDev](https://pkg.go.dev/badge/github.com/ankorstore/yokai-contrib/fxtestcontainer)](https://pkg.go.dev/github.com/ankorstore/yokai-contrib/fxtestcontainer)
8+
9+
> [Yokai](https://github.com/ankorstore/yokai) module for [Testcontainers](https://github.com/testcontainers/testcontainers-go) integration.
10+
11+
<!-- TOC -->
12+
* [Overview](#overview)
13+
* [Installation](#installation)
14+
* [Usage](#usage)
15+
* [Basic Usage](#basic-usage)
16+
* [Advanced Configuration](#advanced-configuration)
17+
* [Testing](#testing)
18+
<!-- TOC -->
19+
20+
## Overview
21+
22+
This module provides a simple and consistent API for creating test containers with [Testcontainers](https://github.com/testcontainers/testcontainers-go) in your [Yokai](https://github.com/ankorstore/yokai) applications.
23+
24+
The module offers the `CreateGenericContainer` function that handles container creation with sensible defaults and flexible configuration options.
25+
26+
## Installation
27+
28+
Install the module:
29+
30+
```shell
31+
go get github.com/ankorstore/yokai-contrib/fxtestcontainer
32+
```
33+
34+
Then activate it in your application bootstrapper:
35+
36+
```go
37+
// internal/bootstrap.go
38+
package internal
39+
40+
import (
41+
"github.com/ankorstore/yokai-contrib/fxtestcontainer"
42+
"github.com/ankorstore/yokai/fxcore"
43+
)
44+
45+
var Bootstrapper = fxcore.NewBootstrapper().WithOptions(
46+
// load modules
47+
fxtestcontainer.FxTestContainerModule,
48+
// ...
49+
)
50+
```
51+
52+
## Usage
53+
54+
### Basic Usage
55+
56+
Use the `CreateGenericContainer` function to create test containers:
57+
58+
```go
59+
package service_test
60+
61+
import (
62+
"context"
63+
"testing"
64+
65+
"github.com/ankorstore/yokai-contrib/fxtestcontainer"
66+
"github.com/stretchr/testify/assert"
67+
"github.com/stretchr/testify/require"
68+
)
69+
70+
func TestMyService_WithRedis(t *testing.T) {
71+
ctx := context.Background()
72+
73+
// Define container configuration
74+
config := &fxtestcontainer.ContainerConfig{
75+
Name: "test-redis",
76+
Image: "redis:alpine",
77+
Port: "6379/tcp",
78+
Environment: map[string]string{
79+
"REDIS_PASSWORD": "",
80+
},
81+
}
82+
83+
// Create test container
84+
container, err := fxtestcontainer.CreateGenericContainer(ctx, config)
85+
require.NoError(t, err)
86+
defer container.Terminate(ctx)
87+
88+
// Get container endpoint
89+
endpoint, err := container.Endpoint(ctx, "")
90+
require.NoError(t, err)
91+
92+
// Use the container in your service
93+
service := NewMyService(endpoint)
94+
95+
// Test your service methods
96+
err = service.Set(ctx, "key", "value")
97+
assert.NoError(t, err)
98+
99+
value, err := service.Get(ctx, "key")
100+
assert.NoError(t, err)
101+
assert.Equal(t, "value", value)
102+
}
103+
```
104+
105+
### Advanced Configuration
106+
107+
The `ContainerConfig` struct provides flexible configuration options:
108+
109+
```go
110+
type ContainerConfig struct {
111+
// Name is a unique identifier for the container
112+
Name string
113+
// Image specifies the Docker image to use
114+
Image string
115+
// Port specifies the main port to expose (convenience field)
116+
Port string
117+
// ExposedPorts lists additional ports to expose
118+
ExposedPorts []string
119+
// Environment provides environment variables
120+
Environment map[string]string
121+
// WaitingFor specifies the wait strategy
122+
WaitingFor wait.Strategy
123+
// Cmd specifies the command to run in the container
124+
Cmd []string
125+
// Mounts specifies volume mounts
126+
Mounts testcontainers.ContainerMounts
127+
}
128+
```
129+
130+
Example with custom wait strategy and multiple configuration options:
131+
132+
```go
133+
func TestWithPostgres(t *testing.T) {
134+
ctx := context.Background()
135+
136+
config := &fxtestcontainer.ContainerConfig{
137+
Name: "test-postgres",
138+
Image: "postgres:13",
139+
Port: "5432/tcp",
140+
Environment: map[string]string{
141+
"POSTGRES_DB": "testdb",
142+
"POSTGRES_USER": "testuser",
143+
"POSTGRES_PASSWORD": "testpass",
144+
},
145+
WaitingFor: wait.ForLog("database system is ready to accept connections"),
146+
}
147+
148+
container, err := fxtestcontainer.CreateGenericContainer(ctx, config)
149+
require.NoError(t, err)
150+
defer container.Terminate(ctx)
151+
152+
// Get connection details
153+
host, err := container.Host(ctx)
154+
require.NoError(t, err)
155+
156+
port, err := container.MappedPort(ctx, "5432")
157+
require.NoError(t, err)
158+
159+
// Use in your tests
160+
dsn := fmt.Sprintf("postgres://testuser:testpass@%s:%s/testdb?sslmode=disable",
161+
host, port.Port())
162+
163+
// Connect to database and run tests...
164+
}
165+
```
166+
167+
## Testing
168+
169+
This module provides a simple and consistent API for creating test containers. See the [test examples](module_test.go) for usage patterns.
170+
171+
The module automatically applies sensible defaults:
172+
- If no `WaitingFor` strategy is provided and a `Port` is specified, it will wait for the port to be listening
173+
- Exposed ports are automatically configured based on the `Port` and `ExposedPorts` fields
174+
- Container names are used for error reporting
175+
- Containers are started automatically and ready to use when the function returns

fxtestcontainer/go.mod

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
module github.com/ankorstore/yokai-contrib/fxtestcontainer
2+
3+
go 1.20
4+
5+
require (
6+
github.com/docker/go-connections v0.4.0
7+
github.com/stretchr/testify v1.10.0
8+
github.com/testcontainers/testcontainers-go v0.26.0
9+
go.uber.org/fx v1.22.2
10+
)
11+
12+
require (
13+
dario.cat/mergo v1.0.0 // indirect
14+
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
15+
github.com/Microsoft/go-winio v0.6.1 // indirect
16+
github.com/Microsoft/hcsshim v0.11.1 // indirect
17+
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
18+
github.com/containerd/containerd v1.7.7 // indirect
19+
github.com/containerd/log v0.1.0 // indirect
20+
github.com/cpuguy83/dockercfg v0.3.1 // indirect
21+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
22+
github.com/docker/distribution v2.8.2+incompatible // indirect
23+
github.com/docker/docker v24.0.7+incompatible // indirect
24+
github.com/docker/go-units v0.5.0 // indirect
25+
github.com/go-ole/go-ole v1.2.6 // indirect
26+
github.com/gogo/protobuf v1.3.2 // indirect
27+
github.com/golang/protobuf v1.5.3 // indirect
28+
github.com/google/uuid v1.6.0 // indirect
29+
github.com/klauspost/compress v1.17.2 // indirect
30+
github.com/kr/pretty v0.3.1 // indirect
31+
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
32+
github.com/magiconair/properties v1.8.7 // indirect
33+
github.com/moby/patternmatcher v0.6.0 // indirect
34+
github.com/moby/sys/sequential v0.5.0 // indirect
35+
github.com/moby/term v0.5.0 // indirect
36+
github.com/morikuni/aec v1.0.0 // indirect
37+
github.com/opencontainers/go-digest v1.0.0 // indirect
38+
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
39+
github.com/opencontainers/runc v1.1.5 // indirect
40+
github.com/pkg/errors v0.9.1 // indirect
41+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
42+
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
43+
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
44+
github.com/shoenig/go-m1cpu v0.1.6 // indirect
45+
github.com/sirupsen/logrus v1.9.3 // indirect
46+
github.com/tklauser/go-sysconf v0.3.12 // indirect
47+
github.com/tklauser/numcpus v0.6.1 // indirect
48+
github.com/yusufpapurcu/wmi v1.2.3 // indirect
49+
go.uber.org/dig v1.18.0 // indirect
50+
go.uber.org/multierr v1.11.0 // indirect
51+
go.uber.org/zap v1.27.0 // indirect
52+
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
53+
golang.org/x/mod v0.15.0 // indirect
54+
golang.org/x/net v0.23.0 // indirect
55+
golang.org/x/sys v0.18.0 // indirect
56+
golang.org/x/time v0.5.0 // indirect
57+
golang.org/x/tools v0.18.0 // indirect
58+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
59+
google.golang.org/grpc v1.62.1 // indirect
60+
google.golang.org/protobuf v1.33.0 // indirect
61+
gopkg.in/yaml.v3 v3.0.1 // indirect
62+
)

0 commit comments

Comments
 (0)