Skip to content

Commit 78579e2

Browse files
committed
unit and integration tests
1 parent 3ab3c3b commit 78579e2

22 files changed

Lines changed: 2000 additions & 46 deletions

File tree

.agent/workflows/agents.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ description: Best practices workflow for building the CAPY Go REST API with type
66

77
This workflow ensures type-safe, reliable, and production-ready Go code for the CAPY club management API.
88

9+
> [!IMPORTANT]
10+
> **NO EMOJIS IN CODE OR COMMITS**
11+
> Do not use emojis in source code comments, commit messages, or pull request descriptions. Keep professional and clean.
12+
13+
914
## Prerequisites
1015

1116
Ensure you have the required tools installed:
@@ -204,32 +209,32 @@ func TestCreateUser_Success(t *testing.T) {
204209
}
205210
```
206211

207-
### Step 4.2: Integration Tests
212+
### Step 4.2: Integration Tests (Testcontainers)
213+
214+
Use `testcontainers-go` for isolated integration testing without managing external Docker Compose services manually.
208215

209216
```go
210217
//go:build integration
211218

212219
func TestUserAPI_Integration(t *testing.T) {
213-
// Setup real DB connection
214-
pool := setupTestDB(t)
220+
// Setup ephemeral Postgres via Testcontainers
221+
pool := testutils.SetupTestDB(t)
215222
defer pool.Close()
216223

217-
// Run migration
218-
runMigrations(t, pool)
219-
220-
// Test CRUD operations
224+
// Test CRUD operations logic
221225
// ...
222226
}
223227
```
224228

225229
### Step 4.3: Run Tests
226230

227231
```bash
228-
# Unit tests only
229-
go test -v -short ./...
232+
# Unit tests only (fast)
233+
go test -v ./...
230234

231-
# All tests including integration
232-
docker-compose up -d db
235+
# All tests including integration (slow, requires Docker)
236+
make test-all
237+
# OR
233238
go test -v -tags=integration ./...
234239
```
235240

@@ -244,7 +249,7 @@ Before deploying any endpoint:
244249
- [ ] **Authentication**: Endpoint uses `middleware.Authenticator`
245250
- [ ] **Authorization**: Role check matches API design (faculty, org_admin, etc.)
246251
- [ ] **Input Validation**: All user input validated with struct tags
247-
- [ ] **SQL Injection**: Using sqlc (parameterized queries) — automatic
252+
- [ ] **SQL Injection**: Using sqlc (parameterized queries) — automatic
248253
- [ ] **Error Handling**: No sensitive info leaked in error messages
249254
- [ ] **Logging**: Sensitive data (passwords, tokens) never logged
250255
- [ ] **Rate Limiting**: Consider adding for public endpoints

.github/workflows/ci.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
name: Test and Lint
12+
runs-on: ubuntu-latest
13+
14+
services:
15+
# Optional: We use testcontainers, but having a service is good for fallback or specific DB tests
16+
postgres:
17+
image: postgres:16-alpine
18+
env:
19+
POSTGRES_USER: test
20+
POSTGRES_PASSWORD: test
21+
POSTGRES_DB: test_db
22+
ports:
23+
- 5432:5432
24+
options: >-
25+
--health-cmd pg_isready
26+
--health-interval 10s
27+
--health-timeout 5s
28+
--health-retries 5
29+
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@v4
33+
34+
- name: Set up Go
35+
uses: actions/setup-go@v5
36+
with:
37+
go-version: '1.25'
38+
cache: true
39+
40+
- name: Install dependencies
41+
run: go mod download
42+
43+
- name: Verify dependencies
44+
run: go mod verify
45+
46+
- name: Install tools
47+
run: |
48+
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
49+
go install github.com/swaggo/swag/cmd/swag@latest
50+
51+
- name: Generate code
52+
run: make generate
53+
54+
- name: Run Linter
55+
uses: golangci/golangci-lint-action@v4
56+
with:
57+
version: latest
58+
args: --timeout=5m
59+
60+
- name: Run Unit Tests
61+
run: make test
62+
63+
- name: Run Integration Tests
64+
run: make test-integration

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test-integration:
2020
go test -v -race -run Integration ./...
2121

2222
test-all:
23-
go test -v -race ./...
23+
go test -v -race -tags=integration ./...
2424

2525
# Linting
2626
lint:

README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# CAPY API
2+
3+
The backend API for the CAPY club management system. Built with Go (Chi), PostgreSQL, and SQLC.
4+
5+
## Features
6+
- **Authentication**: JWT-based auth and OAuth2 (Google/Microsoft) support.
7+
- **Role-Based Access**: Granular permissions for Student, Alumni, Faculty, and External roles.
8+
- **Organization Management**: Create and join organizations (clubs).
9+
- **Event System**: Event scheduling, registration, and attendance tracking.
10+
- **Bot Integration**: API tokens for bot automation.
11+
12+
## Tech Stack
13+
- **Language**: Go 1.25+
14+
- **Router**: [Chi](https://github.com/go-chi/chi)
15+
- **Database**: PostgreSQL
16+
- **ORM-ish**: [sqlc](https://sqlc.dev/) (Type-safe SQL generation)
17+
- **Migration**: [golang-migrate](https://github.com/golang-migrate/migrate)
18+
- **Testing**:
19+
- [Testify](https://github.com/stretchr/testify) (Assertions)
20+
- [Testcontainers](https://github.com/testcontainers/testcontainers-go) (Integration tests)
21+
- [Mockery](https://github.com/vektra/mockery) (Mock generation)
22+
- **Documentation**: Swagger/OpenAPI (via `swag`)
23+
24+
## Prerequisites
25+
- Go 1.25+
26+
- Docker & Docker Compose (for local DB)
27+
- Make
28+
29+
## Getting Started
30+
31+
### 1. Clone & Config
32+
```bash
33+
git clone https://github.com/CAPY-RPI/api.git
34+
cd capy-api
35+
cp .env.example .env
36+
# Edit .env with your local credentials if needed
37+
```
38+
39+
### 2. Start Infrastructure
40+
Start the PostgreSQL database:
41+
```bash
42+
make docker
43+
```
44+
45+
### 3. Run Migrations & Generate Code
46+
```bash
47+
# Install tools if needed (see Step 5 in agents.md or CI workflow)
48+
make generate
49+
```
50+
51+
### 4. Run Server
52+
```bash
53+
make run
54+
# API will be available at http://localhost:8080
55+
# Health check: http://localhost:8080/health
56+
```
57+
58+
## Testing
59+
60+
### Unit Tests
61+
Fast tests running in isolation with mocks.
62+
```bash
63+
make test
64+
```
65+
66+
### Integration Tests
67+
Full-stack tests using ephemeral Docker containers (Postgres). Requires Docker to be running.
68+
```bash
69+
make test-integration
70+
```
71+
72+
### Run All Tests
73+
```bash
74+
make test-all
75+
```
76+
77+
## Project Structure
78+
```
79+
.
80+
├── cmd/server/ # Main entry point
81+
├── internal/
82+
│ ├── config/ # Configuration loading
83+
│ ├── database/ # sqlc generated code & queries
84+
│ ├── dto/ # Data Transfer Objects (Request/Response)
85+
│ ├── handler/ # HTTP Handlers
86+
│ ├── middleware/ # Auth, CORS, Logger middleware
87+
│ ├── router/ # Route definitions
88+
│ └── testutils/ # Testing helpers
89+
├── migrations/ # SQL migration files
90+
├── tests/integration/ # End-to-end integration tests
91+
└── schema.sql # Current database schema
92+
```
93+
94+
## CI/CD
95+
This project uses GitHub Actions for continuous integration.
96+
- **Workflow**: `.github/workflows/ci.yml`
97+
- **Checks**: Linting (`golangci-lint`), Unit Tests, Integration Tests.

cmd/server/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func main() {
4444
h := handler.New(queries, cfg)
4545

4646
// Setup router
47-
r := router.New(h, queries, cfg.JWT.Secret)
47+
r := router.New(h, queries, cfg.JWT.Secret, cfg.Server.AllowedOrigins)
4848

4949
// Create server
5050
addr := cfg.Server.Host + ":" + cfg.Server.Port

go.mod

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,74 @@ require (
88
github.com/google/uuid v1.6.0
99
github.com/ilyakaznacheev/cleanenv v1.5.0
1010
github.com/jackc/pgx/v5 v5.8.0
11+
github.com/stretchr/testify v1.11.1
12+
github.com/testcontainers/testcontainers-go v0.40.0
13+
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0
1114
golang.org/x/crypto v0.47.0
1215
golang.org/x/oauth2 v0.34.0
1316
)
1417

1518
require (
16-
cloud.google.com/go/compute/metadata v0.3.0 // indirect
19+
cloud.google.com/go/compute/metadata v0.9.0 // indirect
20+
dario.cat/mergo v1.0.2 // indirect
21+
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
1722
github.com/BurntSushi/toml v1.2.1 // indirect
23+
github.com/Microsoft/go-winio v0.6.2 // indirect
24+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
25+
github.com/containerd/errdefs v1.0.0 // indirect
26+
github.com/containerd/errdefs/pkg v0.3.0 // indirect
27+
github.com/containerd/log v0.1.0 // indirect
28+
github.com/containerd/platforms v0.2.1 // indirect
29+
github.com/cpuguy83/dockercfg v0.3.2 // indirect
30+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
31+
github.com/distribution/reference v0.6.0 // indirect
32+
github.com/docker/docker v28.5.1+incompatible // indirect
33+
github.com/docker/go-connections v0.6.0 // indirect
34+
github.com/docker/go-units v0.5.0 // indirect
35+
github.com/ebitengine/purego v0.8.4 // indirect
36+
github.com/felixge/httpsnoop v1.0.4 // indirect
37+
github.com/go-logr/logr v1.4.3 // indirect
38+
github.com/go-logr/stdr v1.2.2 // indirect
39+
github.com/go-ole/go-ole v1.2.6 // indirect
40+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
1841
github.com/jackc/pgpassfile v1.0.0 // indirect
1942
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
2043
github.com/jackc/puddle/v2 v2.2.2 // indirect
2144
github.com/joho/godotenv v1.5.1 // indirect
22-
github.com/kr/text v0.2.0 // indirect
23-
github.com/rogpeppe/go-internal v1.14.1 // indirect
45+
github.com/klauspost/compress v1.18.0 // indirect
46+
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
47+
github.com/magiconair/properties v1.8.10 // indirect
48+
github.com/moby/docker-image-spec v1.3.1 // indirect
49+
github.com/moby/go-archive v0.1.0 // indirect
50+
github.com/moby/patternmatcher v0.6.0 // indirect
51+
github.com/moby/sys/sequential v0.6.0 // indirect
52+
github.com/moby/sys/user v0.4.0 // indirect
53+
github.com/moby/sys/userns v0.1.0 // indirect
54+
github.com/moby/term v0.5.0 // indirect
55+
github.com/morikuni/aec v1.0.0 // indirect
56+
github.com/opencontainers/go-digest v1.0.0 // indirect
57+
github.com/opencontainers/image-spec v1.1.1 // indirect
58+
github.com/pkg/errors v0.9.1 // indirect
59+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
60+
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
61+
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
62+
github.com/sirupsen/logrus v1.9.3 // indirect
63+
github.com/stretchr/objx v0.5.2 // indirect
64+
github.com/tklauser/go-sysconf v0.3.12 // indirect
65+
github.com/tklauser/numcpus v0.6.1 // indirect
66+
github.com/yusufpapurcu/wmi v1.2.4 // indirect
67+
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
68+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
69+
go.opentelemetry.io/otel v1.38.0 // indirect
70+
go.opentelemetry.io/otel/metric v1.38.0 // indirect
71+
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
72+
go.opentelemetry.io/otel/trace v1.38.0 // indirect
2473
golang.org/x/sync v0.19.0 // indirect
74+
golang.org/x/sys v0.40.0 // indirect
2575
golang.org/x/text v0.33.0 // indirect
76+
golang.org/x/time v0.8.0 // indirect
77+
google.golang.org/grpc v1.78.0 // indirect
78+
google.golang.org/protobuf v1.36.11 // indirect
2679
gopkg.in/yaml.v3 v3.0.1 // indirect
2780
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
2881
)

0 commit comments

Comments
 (0)