Skip to content

Commit

Permalink
Merge pull request #59 from DATA-DOG/tests
Browse files Browse the repository at this point in the history
Refactor tests to work with testcontainers
  • Loading branch information
Yiling-J authored Jan 6, 2024
2 parents f2e4df2 + ae09091 commit 8a12fdc
Show file tree
Hide file tree
Showing 8 changed files with 3,314 additions and 391 deletions.
33 changes: 3 additions & 30 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,13 @@ jobs:
strategy:
matrix:
go: ["1.18.x", "1.19.x", "1.20.x", "1.21.x"]
services:
mysql8:
image: mysql:8
env:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: pass
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -ppass"
--health-interval 10s
--health-start-period 10s
--health-timeout 5s
--health-retries 10
postgres15:
image: postgres:15
env:
POSTGRES_DB: test
POSTGRES_PASSWORD: pass
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}
- name: Create Table
run: |
make mysql
make psql
- name: Run integration tests
env:
MYSQL_DSN: AUTO
PSQL_DSN: AUTO
run: go test ./...
54 changes: 3 additions & 51 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,52 +1,4 @@
define MYSQL_SQL
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
username VARCHAR(32) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX uniq_email (email)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
endef

define PSQL_SQL
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(32) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL
);
endef

export MYSQL_SQL
MYSQL := "$$MYSQL_SQL"

export PSQL_SQL
PSQL := "$$PSQL_SQL"

INSERTS := "INSERT INTO users (username, email) VALUES ('gopher', '[email protected]'), ('john', '[email protected]'), ('jane', '[email protected]');"

MYSQLCMD=mysql
ifndef CI
MYSQLCMD=docker compose exec mysql mysql
endif

PSQLCMD=psql
ifndef CI
PSQLCMD=docker compose exec postgres psql
endif

test: MYSQL_DSN=root:pass@/txdb_test
test: PSQL_DSN=postgres://postgres:pass@localhost/txdb_test
test: mysql psql
@go test -race -tags "mysql psql"

mysql:
@$(MYSQLCMD) -h 127.0.0.1 -u root -ppass -e 'DROP DATABASE IF EXISTS txdb_test'
@$(MYSQLCMD) -h 127.0.0.1 -u root -ppass -e 'CREATE DATABASE txdb_test'
@$(MYSQLCMD) -h 127.0.0.1 -u root -ppass txdb_test -e $(MYSQL)
@$(MYSQLCMD) -h 127.0.0.1 -u root -ppass txdb_test -e $(INSERTS)

psql:
@$(PSQLCMD) "postgresql://postgres:[email protected]" -c 'DROP DATABASE IF EXISTS txdb_test'
@$(PSQLCMD) "postgresql://postgres:[email protected]" -c 'CREATE DATABASE txdb_test'
@$(PSQLCMD) "postgresql://postgres:[email protected]/txdb_test" -c $(PSQL)
@$(PSQLCMD) "postgresql://postgres:[email protected]/txdb_test" -c $(INSERTS)

.PHONY: test mysql psql
@go test -race
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,19 @@ Every time you will run this application, it will remain in the same state as be

### Testing

Usage is mainly intended for testing purposes. See the **db_test.go** as
an example. In order to run tests, you will need docker and
docker compose:
Usage is mainly intended for testing purposes. Tests require database access, support using `postgres` and `mysql` databases. The easiest way to do this is by using [testcontainers](https://golang.testcontainers.org/), which is enabled by setting the respective database DSN values to `AUTO`. Example:

docker compose up
make test
```bash
MYSQL_DSN=AUTO PSQL_DSN=AUTO go test ./...
```

If you wish to use a running local database instance, you can also provide the DSN directly, and it will be used:

```bash
MYSQL_DSN=root:pass@/ PSQL_DSN=postgres://postgres:pass@localhost/ go test ./...
```

The tests are currently using `postgres` and `mysql` databases
To run tests only against MySQL or PostgreSQL, you may provide only the respective DSN values; any unset DSN is skipped for tests.

### Documentation

Expand Down
111 changes: 111 additions & 0 deletions bootstrap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package txdb_test

import (
"context"
"database/sql"
"strings"
"testing"
"time"

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

const (
mysql_sql = `CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
username VARCHAR(32) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX uniq_email (email)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB`

psql_sql = `CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(32) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL
)`

inserts = `INSERT INTO users (username, email) VALUES ('gopher', '[email protected]'), ('john', '[email protected]'), ('jane', '[email protected]')`

testDB = "txdb_test"
)

// bootstrap bootstraps the database for tests.
func bootstrap(t *testing.T, driver, dsn string) {
db, err := sql.Open(driver, dsn)
if err != nil {
t.Fatal(err)
}
switch driver {
case "mysql":
if _, err := db.Exec(mysql_sql); err != nil {
t.Fatal(err)
}
case "postgres":
if _, err := db.Exec(psql_sql); err != nil {
t.Fatal(err)
}
default:
panic("unrecognized driver: " + driver)
}
if _, err := db.Exec(inserts); err != nil {
t.Fatal(err)
}
}

func createDB(t *testing.T, driver, dsn string) {
db, err := sql.Open(driver, dsn)
if err != nil {
t.Fatal(err)
}
if _, err := db.Exec("DROP DATABASE IF EXISTS " + testDB); err != nil {
t.Fatal(err)
}
if _, err := db.Exec("CREATE DATABASE " + testDB); err != nil {
t.Fatal(err)
}
}

func startPostgres(t *testing.T) string {
ctx := context.Background()

postgresContainer, err := postgres.RunContainer(ctx,
testcontainers.WithImage("docker.io/postgres:15.2-alpine"),
postgres.WithDatabase(testDB),
testcontainers.WithWaitStrategy(
wait.ForLog("database system is ready to accept connections").
WithOccurrence(2).
WithStartupTimeout(5*time.Second)),
)
if err != nil {
t.Fatal(err)
}

dsn, err := postgresContainer.ConnectionString(ctx)
if err != nil {
t.Fatal(err)
}
return strings.TrimSuffix(dsn, testDB+"?")
}

func startMySQL(t *testing.T) string {
ctx := context.Background()

mysqlContainer, err := mysql.RunContainer(ctx,
testcontainers.WithImage("mysql:8"),
mysql.WithUsername("root"),
mysql.WithPassword("password"),
mysql.WithDatabase(testDB),
)
if err != nil {
t.Fatal(err)
}
dsn, err := mysqlContainer.ConnectionString(ctx)
if err != nil {
t.Fatal(err)
}
return strings.TrimSuffix(dsn, testDB)
}
Loading

0 comments on commit 8a12fdc

Please sign in to comment.