188 lines
4.1 KiB
Markdown
188 lines
4.1 KiB
Markdown
# Integration Testing
|
|
|
|
## Docker Compose Fixture
|
|
|
|
Create `pkg/myfeature/testdata/docker-compose.yml` for test services:
|
|
|
|
```yaml
|
|
version: "3.8"
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
environment:
|
|
POSTGRES_USER: test
|
|
POSTGRES_PASSWORD: test
|
|
POSTGRES_DB: testdb
|
|
ports:
|
|
- "5433:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U test"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports:
|
|
- "6380:6379"
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
```
|
|
|
|
## SQL Schema Fixture
|
|
|
|
Create `pkg/myfeature/testdata/schema.sql` for database initialization:
|
|
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS orders (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER REFERENCES users(id),
|
|
amount DECIMAL(10,2) NOT NULL,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
## Test Data Fixture
|
|
|
|
Create `pkg/myfeature/testdata/testdata.sql`:
|
|
|
|
```sql
|
|
INSERT INTO users (name, email) VALUES
|
|
('Alice Johnson', 'alice@example.com'),
|
|
('Bob Smith', 'bob@example.com'),
|
|
('Charlie Brown', 'charlie@example.com');
|
|
|
|
INSERT INTO orders (user_id, amount, status) VALUES
|
|
(1, 100.00, 'completed'),
|
|
(1, 50.00, 'pending'),
|
|
(2, 200.00, 'completed');
|
|
```
|
|
|
|
## Using Fixtures in Tests
|
|
|
|
```go
|
|
//go:build integration
|
|
|
|
package database_test
|
|
|
|
import (
|
|
"database/sql"
|
|
"os"
|
|
"os/exec"
|
|
"testing"
|
|
"time"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
type DatabaseTestSuite struct {
|
|
suite.Suite
|
|
db *sql.DB
|
|
}
|
|
|
|
func (s *DatabaseTestSuite) SetupSuite() {
|
|
cmd := exec.Command("docker-compose", "-f", "testdata/docker-compose.yml", "up", "-d")
|
|
if err := cmd.Run(); err != nil {
|
|
s.T().Fatalf("failed to start docker-compose: %v", err)
|
|
}
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
db, err := sql.Open("postgres", "postgres://test:test@localhost:5433/testdb?sslmode=disable")
|
|
if err != nil {
|
|
s.T().Fatalf("failed to connect to database: %v", err)
|
|
}
|
|
s.db = db
|
|
|
|
schema, _ := os.ReadFile("testdata/schema.sql")
|
|
_, err = db.Exec(string(schema))
|
|
if err != nil {
|
|
s.T().Fatalf("failed to run schema: %v", err)
|
|
}
|
|
}
|
|
|
|
func (s *DatabaseTestSuite) TearDownSuite() {
|
|
cmd := exec.Command("docker-compose", "-f", "testdata/docker-compose.yml", "down", "-v")
|
|
_ = cmd.Run()
|
|
}
|
|
|
|
func (s *DatabaseTestSuite) SetupTest() {
|
|
_, err := s.db.Exec("TRUNCATE TABLE orders, users CASCADE")
|
|
if err != nil {
|
|
s.T().Fatalf("failed to clear database: %v", err)
|
|
}
|
|
|
|
testdata, _ := os.ReadFile("testdata/testdata.sql")
|
|
_, err = s.db.Exec(string(testdata))
|
|
if err != nil {
|
|
s.T().Fatalf("failed to load test data: %v", err)
|
|
}
|
|
}
|
|
|
|
func (s *DatabaseTestSuite) TestUserCount() {
|
|
is := assert.New(s.T())
|
|
|
|
var count int
|
|
err := s.db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
|
|
is.NoError(err)
|
|
is.Equal(3, count)
|
|
}
|
|
|
|
func (s *DatabaseTestSuite) TestOrderSum() {
|
|
is := assert.New(s.T())
|
|
|
|
var sum float64
|
|
err := s.db.QueryRow("SELECT SUM(amount) FROM orders").Scan(&sum)
|
|
is.NoError(err)
|
|
is.InDelta(350.0, sum, 0.01)
|
|
}
|
|
|
|
func TestDatabaseTestSuite(t *testing.T) {
|
|
suite.Run(t, new(DatabaseTestSuite))
|
|
}
|
|
```
|
|
|
|
## Test Helper with Embedded Fixtures
|
|
|
|
```go
|
|
package myfeature
|
|
|
|
import (
|
|
"database/sql"
|
|
"embed"
|
|
)
|
|
|
|
//go:embed testdata/schema.sql testdata/testdata.sql
|
|
var fixtures embed.FS
|
|
|
|
func SetupDB(db *sql.DB) error {
|
|
schema, err := fixtures.ReadFile("testdata/schema.sql")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := db.Exec(string(schema)); err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := fixtures.ReadFile("testdata/testdata.sql")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := db.Exec(string(data)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
```
|