Skip to content

Commit

Permalink
feat: support for generating testcontainers-go tests for DB drivers (#…
Browse files Browse the repository at this point in the history
…271)

add testcontainers feature
  • Loading branch information
mdelapenya authored Jul 24, 2024
1 parent 362a4e9 commit fa8fb47
Show file tree
Hide file tree
Showing 15 changed files with 447 additions and 1 deletion.
34 changes: 34 additions & 0 deletions .github/workflows/testcontainers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Integrations Test for the Generated Blueprints

on:
pull_request: {}
workflow_dispatch: {}

jobs:
itests_matrix:
strategy:
matrix:
driver:
[mysql, postgres, mongo, redis]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22.x'

- name: Commit report
run: |
git config --global user.name 'testname'
git config --global user.email 'testemail@users.noreply.github.com'
- name: build ${{ matrix.driver }} template
run: script -q /dev/null -c "go run main.go create -n ${{ matrix.driver }} -g commit -f fiber -d ${{matrix.driver}}" /dev/null

- name: run ${{ matrix.driver }} integration tests
working-directory: ${{ matrix.driver }}
run: make itest

- name: remove ${{ matrix.driver }} template
run: rm -rf ${{ matrix.driver }}
13 changes: 13 additions & 0 deletions cmd/program/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type Templater interface {
type DBDriverTemplater interface {
Service() []byte
Env() []byte
Tests() []byte
}

type DockerTemplater interface {
Expand Down Expand Up @@ -287,6 +288,15 @@ func (p *Project) CreateMainFile() error {
cobra.CheckErr(err)
return err
}

if p.DBDriver != "sqlite" {
err = p.CreateFileWithInjection(internalDatabasePath, projectPath, "database_test.go", "integration-tests")
if err != nil {
log.Printf("Error injecting database_test.go file: %v", err)
cobra.CheckErr(err)
return err
}
}
}

// Create correct docker compose for the selected driver
Expand Down Expand Up @@ -708,6 +718,9 @@ func (p *Project) CreateFileWithInjection(pathToCreate string, projectPath strin
case "db-docker":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.DockerMap[p.Docker].templater.Docker())))
err = createdTemplate.Execute(createdFile, p)
case "integration-tests":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.DBDriverMap[p.DBDriver].templater.Tests())))
err = createdTemplate.Execute(createdFile, p)
case "tests":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.FrameworkMap[p.ProjectType].templater.TestHandler())))
err = createdTemplate.Execute(createdFile, p)
Expand Down
61 changes: 61 additions & 0 deletions cmd/template/dbdriver/files/tests/mongo.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package database

import (
"context"
"log"
"testing"

"github.com/testcontainers/testcontainers-go/modules/mongodb"
)

func mustStartMongoContainer() (func(context.Context) error, error) {
dbContainer, err := mongodb.Run(context.Background(), "mongo:latest")
if err != nil {
return nil, err
}

dbHost, err := dbContainer.Host(context.Background())
if err != nil {
return dbContainer.Terminate, err
}

dbPort, err := dbContainer.MappedPort(context.Background(), "27017/tcp")
if err != nil {
return dbContainer.Terminate, err
}

host = dbHost
port = dbPort.Port()

return dbContainer.Terminate, err
}

func TestMain(m *testing.M) {
teardown, err := mustStartMongoContainer()
if err != nil {
log.Fatalf("could not start postgres container: %v", err)
}

m.Run()

if teardown != nil && teardown(context.Background()) != nil {
log.Fatalf("could not teardown postgres container: %v", err)
}
}

func TestNew(t *testing.T) {
srv := New()
if srv == nil {
t.Fatal("New() returned nil")
}
}

func TestHealth(t *testing.T) {
srv := New()

stats := srv.Health()

if stats["message"] != "It's healthy" {
t.Fatalf("expected message to be 'It's healthy', got %s", stats["message"])
}
}
96 changes: 96 additions & 0 deletions cmd/template/dbdriver/files/tests/mysql.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package database

import (
"context"
"log"
"testing"
"time"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/mysql"
"github.com/testcontainers/testcontainers-go/wait"
)

func mustStartMySQLContainer() (func(context.Context) error, error) {
var (
dbName = "database"
dbPwd = "password"
dbUser = "user"
)

dbContainer, err := mysql.Run(context.Background(),
"mysql:8.0.36",
mysql.WithDatabase(dbName),
mysql.WithUsername(dbUser),
mysql.WithPassword(dbPwd),
testcontainers.WithWaitStrategy(wait.ForLog("port: 3306 MySQL Community Server - GPL").WithStartupTimeout(30*time.Second)),
)
if err != nil {
return nil, err
}

dbname = dbName
password = dbPwd
username = dbUser

dbHost, err := dbContainer.Host(context.Background())
if err != nil {
return dbContainer.Terminate, err
}

dbPort, err := dbContainer.MappedPort(context.Background(), "3306/tcp")
if err != nil {
return dbContainer.Terminate, err
}

host = dbHost
port = dbPort.Port()

return dbContainer.Terminate, err
}

func TestMain(m *testing.M) {
teardown, err := mustStartMySQLContainer()
if err != nil {
log.Fatalf("could not start mysql container: %v", err)
}

m.Run()

if teardown != nil && teardown(context.Background()) != nil {
log.Fatalf("could not teardown mysql container: %v", err)
}
}

func TestNew(t *testing.T) {
srv := New()
if srv == nil {
t.Fatal("New() returned nil")
}
}

func TestHealth(t *testing.T) {
srv := New()

stats := srv.Health()

if stats["status"] != "up" {
t.Fatalf("expected status to be up, got %s", stats["status"])
}

if _, ok := stats["error"]; ok {
t.Fatalf("expected error not to be present")
}

if stats["message"] != "It's healthy" {
t.Fatalf("expected message to be 'It's healthy', got %s", stats["message"])
}
}

func TestClose(t *testing.T) {
srv := New()

if srv.Close() != nil {
t.Fatalf("expected Close() to return nil")
}
}
100 changes: 100 additions & 0 deletions cmd/template/dbdriver/files/tests/postgres.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package database

import (
"context"
"log"
"testing"
"time"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"github.com/testcontainers/testcontainers-go/wait"
)

func mustStartPostgresContainer() (func(context.Context) error, error) {
var (
dbName = "database"
dbPwd = "password"
dbUser = "user"
)

dbContainer, err := postgres.Run(
context.Background(),
"postgres:latest",
postgres.WithDatabase(dbName),
postgres.WithUsername(dbUser),
postgres.WithPassword(dbPwd),
testcontainers.WithWaitStrategy(
wait.ForLog("database system is ready to accept connections").
WithOccurrence(2).
WithStartupTimeout(5*time.Second)),
)
if err != nil {
return nil, err
}

database = dbName
password = dbPwd
username = dbUser

dbHost, err := dbContainer.Host(context.Background())
if err != nil {
return dbContainer.Terminate, err
}

dbPort, err := dbContainer.MappedPort(context.Background(), "5432/tcp")
if err != nil {
return dbContainer.Terminate, err
}

host = dbHost
port = dbPort.Port()

return dbContainer.Terminate, err
}

func TestMain(m *testing.M) {
teardown, err := mustStartPostgresContainer()
if err != nil {
log.Fatalf("could not start postgres container: %v", err)
}

m.Run()

if teardown != nil && teardown(context.Background()) != nil {
log.Fatalf("could not teardown postgres container: %v", err)
}
}

func TestNew(t *testing.T) {
srv := New()
if srv == nil {
t.Fatal("New() returned nil")
}
}

func TestHealth(t *testing.T) {
srv := New()

stats := srv.Health()

if stats["status"] != "up" {
t.Fatalf("expected status to be up, got %s", stats["status"])
}

if _, ok := stats["error"]; ok {
t.Fatalf("expected error not to be present")
}

if stats["message"] != "It's healthy" {
t.Fatalf("expected message to be 'It's healthy', got %s", stats["message"])
}
}

func TestClose(t *testing.T) {
srv := New()

if srv.Close() != nil {
t.Fatalf("expected Close() to return nil")
}
}
Loading

0 comments on commit fa8fb47

Please sign in to comment.