A lot more tests

This commit is contained in:
Hein
2025-12-08 16:56:48 +02:00
parent aeae9d7e0c
commit c9eaf84125
28 changed files with 4036 additions and 444 deletions

265
tests/INTEGRATION_TESTS.md Normal file
View File

@@ -0,0 +1,265 @@
# Integration Tests
This document describes how to run integration tests for ResolveSpec packages with a PostgreSQL database.
## Overview
Integration tests validate the full functionality of both `pkg/resolvespec` and `pkg/restheadspec` packages with an actual PostgreSQL database. These tests cover:
- CRUD operations (Create, Read, Update, Delete)
- Filtering and sorting
- Pagination
- Column selection
- Relationship preloading
- Metadata generation
- Query parameter parsing
- CORS handling
## Prerequisites
- Go 1.19 or later
- PostgreSQL 12 or later
- Docker and Docker Compose (optional, for easy setup)
## Quick Start with Docker
### 1. Start PostgreSQL with Docker Compose
```bash
docker-compose up -d postgres-test
```
This starts a PostgreSQL container with the following default settings:
- Host: localhost
- Port: 5432
- User: postgres
- Password: postgres
- Databases: resolvespec_test, restheadspec_test
### 2. Run Integration Tests
```bash
# Run all integration tests
go test -tags=integration ./pkg/resolvespec ./pkg/restheadspec -v
# Run only resolvespec integration tests
go test -tags=integration ./pkg/resolvespec -v
# Run only restheadspec integration tests
go test -tags=integration ./pkg/restheadspec -v
```
### 3. Stop PostgreSQL
```bash
docker-compose down
```
## Manual PostgreSQL Setup
If you prefer to use an existing PostgreSQL installation:
### 1. Create Test Databases
```sql
CREATE DATABASE resolvespec_test;
CREATE DATABASE restheadspec_test;
```
### 2. Set Environment Variable
```bash
# For resolvespec tests
export TEST_DATABASE_URL="host=localhost user=postgres password=yourpassword dbname=resolvespec_test port=5432 sslmode=disable"
# For restheadspec tests (uses same env var with different dbname)
export TEST_DATABASE_URL="host=localhost user=postgres password=yourpassword dbname=restheadspec_test port=5432 sslmode=disable"
```
### 3. Run Tests
```bash
go test -tags=integration ./pkg/resolvespec ./pkg/restheadspec -v
```
## Test Coverage
### pkg/resolvespec Integration Tests
| Test | Description |
|------|-------------|
| `TestIntegration_CreateOperation` | Tests creating new records via API |
| `TestIntegration_ReadOperation` | Tests reading all records with pagination |
| `TestIntegration_ReadWithFilters` | Tests filtering records (e.g., age > 25) |
| `TestIntegration_UpdateOperation` | Tests updating existing records |
| `TestIntegration_DeleteOperation` | Tests deleting records |
| `TestIntegration_MetadataOperation` | Tests retrieving table metadata |
| `TestIntegration_ReadWithPreload` | Tests eager loading relationships |
### pkg/restheadspec Integration Tests
| Test | Description |
|------|-------------|
| `TestIntegration_GetAllUsers` | Tests GET request to retrieve all records |
| `TestIntegration_GetUsersWithFilters` | Tests header-based filtering |
| `TestIntegration_GetUsersWithPagination` | Tests limit/offset pagination |
| `TestIntegration_GetUsersWithSorting` | Tests sorting by column |
| `TestIntegration_GetUsersWithColumnsSelection` | Tests selecting specific columns |
| `TestIntegration_GetUsersWithPreload` | Tests relationship preloading |
| `TestIntegration_GetMetadata` | Tests metadata endpoint |
| `TestIntegration_OptionsRequest` | Tests OPTIONS/CORS handling |
| `TestIntegration_QueryParamsOverHeaders` | Tests query param precedence |
| `TestIntegration_GetSingleRecord` | Tests retrieving single record by ID |
## Test Data
Integration tests use the following test models:
### TestUser
```go
type TestUser struct {
ID uint
Name string
Email string (unique)
Age int
Active bool
CreatedAt time.Time
Posts []TestPost
}
```
### TestPost
```go
type TestPost struct {
ID uint
UserID uint
Title string
Content string
Published bool
CreatedAt time.Time
User *TestUser
Comments []TestComment
}
```
### TestComment
```go
type TestComment struct {
ID uint
PostID uint
Content string
CreatedAt time.Time
Post *TestPost
}
```
## Troubleshooting
### Connection Refused
If you see "connection refused" errors:
1. Check that PostgreSQL is running:
```bash
docker-compose ps
```
2. Verify connection parameters:
```bash
psql -h localhost -U postgres -d resolvespec_test
```
3. Check firewall settings if using remote PostgreSQL
### Permission Denied
Ensure the PostgreSQL user has necessary permissions:
```sql
GRANT ALL PRIVILEGES ON DATABASE resolvespec_test TO postgres;
GRANT ALL PRIVILEGES ON DATABASE restheadspec_test TO postgres;
```
### Tests Fail with "relation does not exist"
The tests automatically run migrations, but if you encounter this error:
1. Ensure your DATABASE_URL environment variable is correct
2. Check that the database exists
3. Verify the user has CREATE TABLE permissions
### Clean Database Between Runs
Each test automatically cleans up its data using `TRUNCATE`. If you need a fresh database:
```bash
# Stop and remove containers (removes data)
docker-compose down -v
# Restart
docker-compose up -d postgres-test
```
## CI/CD Integration
### GitHub Actions Example
```yaml
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: resolvespec_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Run integration tests
env:
TEST_DATABASE_URL: "host=localhost user=postgres password=postgres dbname=resolvespec_test port=5432 sslmode=disable"
run: |
go test -tags=integration ./pkg/resolvespec -v
go test -tags=integration ./pkg/restheadspec -v
```
## Performance Considerations
- Integration tests are slower than unit tests due to database I/O
- Each test sets up and tears down test data
- Consider running integration tests separately from unit tests in CI/CD
- Use connection pooling for better performance
## Best Practices
1. **Isolation**: Each test cleans up its data using TRUNCATE
2. **Independent**: Tests don't depend on each other's state
3. **Idempotent**: Tests can be run multiple times safely
4. **Fast Setup**: Migrations run automatically
5. **Flexible**: Works with any PostgreSQL instance via environment variables
## Additional Resources
- [PostgreSQL Docker Image](https://hub.docker.com/_/postgres)
- [GORM Documentation](https://gorm.io/)
- [Testing in Go](https://golang.org/doc/tutorial/add-a-test)

135
tests/QUICKSTART_TESTING.md Normal file
View File

@@ -0,0 +1,135 @@
# Testing Quick Start
## ⚡ 30-Second Start
```bash
# Unit tests (no setup required)
go test ./pkg/resolvespec ./pkg/restheadspec -v
# Integration tests (automated)
./scripts/run-integration-tests.sh
```
## 📋 Common Commands
| What You Want | Command |
|---------------|---------|
| Run unit tests | `make test-unit` |
| Run integration tests | `./scripts/run-integration-tests.sh` |
| Run all tests | `make test` |
| Coverage report | `make coverage` |
| Start PostgreSQL | `make docker-up` |
| Stop PostgreSQL | `make docker-down` |
| See all commands | `make help` |
## 📊 Current Test Coverage
- **pkg/resolvespec**: 11.2% (28 unit + 7 integration tests)
- **pkg/restheadspec**: 12.5% (50 unit + 10 integration tests)
- **Total**: 95 tests
## 🧪 Test Types
### Unit Tests (Fast, No Database)
Test individual functions and components in isolation.
```bash
go test ./pkg/resolvespec -v
go test ./pkg/restheadspec -v
```
### Integration Tests (Requires PostgreSQL)
Test full API operations with real database.
```bash
# Automated (recommended)
./scripts/run-integration-tests.sh
# Manual
make docker-up
go test -tags=integration ./pkg/resolvespec -v
make docker-down
```
## 🔍 Run Specific Tests
```bash
# Run a specific test function
go test ./pkg/resolvespec -run TestHookRegistry -v
# Run tests matching a pattern
go test ./pkg/resolvespec -run "TestHook.*" -v
# Run integration test for specific feature
go test -tags=integration ./pkg/restheadspec -run TestIntegration_GetUsersWithFilters -v
```
## 📈 Coverage Reports
```bash
# Generate HTML coverage report
make coverage
# View in terminal
go test ./pkg/resolvespec -cover
```
## 🐛 Troubleshooting
| Problem | Solution |
|---------|----------|
| "No tests found" | Use `-tags=integration` for integration tests |
| "Connection refused" | Run `make docker-up` to start PostgreSQL |
| "Permission denied" | Run `chmod +x scripts/run-integration-tests.sh` |
| Tests fail randomly | Use `-race` flag to detect race conditions |
## 📚 Full Documentation
- **Complete Guide**: [README_TESTS.md](./README_TESTS.md)
- **Integration Details**: [INTEGRATION_TESTS.md](./INTEGRATION_TESTS.md)
- **All Commands**: `make help`
## 🎯 What Gets Tested?
### pkg/resolvespec
- ✅ Context operations
- ✅ Hook system
- ✅ CRUD operations (Create, Read, Update, Delete)
- ✅ Filtering and sorting
- ✅ Relationship preloading
- ✅ Metadata generation
### pkg/restheadspec
- ✅ Header-based API operations
- ✅ Query parameter parsing
- ✅ Pagination (limit/offset)
- ✅ Column selection
- ✅ CORS handling
- ✅ Sorting by columns
## 🚀 CI/CD
GitHub Actions workflow is ready at `.github/workflows/tests.yml`
Tests run automatically on:
- Push to main/develop branches
- Pull requests
## 💡 Tips
1. **Run unit tests frequently** - They're fast (< 1 second)
2. **Run integration tests before commits** - Catches DB issues
3. **Use `make test-integration-docker`** - Handles everything automatically
4. **Check coverage reports** - Identify untested code
5. **Use `-v` flag** - See detailed test output
## 🎓 Next Steps
1. Run unit tests: `make test-unit`
2. Try integration tests: `./scripts/run-integration-tests.sh`
3. Generate coverage: `make coverage`
4. Read full guide: `README_TESTS.md`
---
**Need Help?** Check [README_TESTS.md](./README_TESTS.md) for detailed instructions.

351
tests/README_TESTS.md Normal file
View File

@@ -0,0 +1,351 @@
# Testing Guide
This document provides a comprehensive guide to running tests for the ResolveSpec project.
## Table of Contents
- [Quick Start](#quick-start)
- [Unit Tests](#unit-tests)
- [Integration Tests](#integration-tests)
- [Test Coverage](#test-coverage)
- [CI/CD](#cicd)
## Quick Start
### Run All Unit Tests
```bash
# Simple
go test ./pkg/resolvespec ./pkg/restheadspec -v
# With coverage
make test-unit
```
### Run Integration Tests (Automated with Docker)
```bash
# Easiest way - handles Docker automatically
./scripts/run-integration-tests.sh
# Or with make
make test-integration-docker
# Run specific package
./scripts/run-integration-tests.sh resolvespec
./scripts/run-integration-tests.sh restheadspec
```
### Run All Tests
```bash
make test
```
## Unit Tests
Unit tests are located alongside the source files with `_test.go` suffix and **do not** require a database.
### Test Structure
```
pkg/
├── resolvespec/
│ ├── context.go
│ ├── context_test.go # Unit tests
│ ├── handler.go
│ ├── handler_test.go # Unit tests
│ ├── hooks.go
│ ├── hooks_test.go # Unit tests
│ └── integration_test.go # Integration tests
└── restheadspec/
├── context.go
├── context_test.go # Unit tests
└── integration_test.go # Integration tests
```
### Coverage Report
#### Current Coverage
- **pkg/resolvespec**: 11.2% (improved from 0%)
- **pkg/restheadspec**: 12.5% (improved from 10.5%)
#### What's Tested
##### pkg/resolvespec
- ✅ Context operations (WithSchema, GetEntity, etc.)
- ✅ Hook registry (register, execute, clear)
- ✅ Handler initialization
- ✅ Utility functions (parseModelName, buildRoutePath, toSnakeCase)
- ✅ Column type detection
- ✅ Table name parsing
##### pkg/restheadspec
- ✅ Context operations including options
- ✅ Hook system
- ✅ Header parsing and decoding
- ✅ Query parameter parsing
- ✅ Nested relation detection
- ✅ Row number operations
### Running Specific Tests
```bash
# Run specific test function
go test ./pkg/resolvespec -run TestHookRegistry -v
# Run tests matching pattern
go test ./pkg/resolvespec -run "TestHook.*" -v
# Run with coverage
go test ./pkg/resolvespec -cover
# Generate HTML coverage report
go test ./pkg/resolvespec -coverprofile=coverage.out
go tool cover -html=coverage.out
```
## Integration Tests
Integration tests require a PostgreSQL database and use the `// +build integration` tag.
### Prerequisites
**Option 1: Docker (Recommended)**
- Docker and Docker Compose installed
**Option 2: Manual PostgreSQL**
- PostgreSQL 12+ installed and running
- Create test databases manually (see below)
### Setup with Docker
1. **Start PostgreSQL**:
```bash
make docker-up
# or
docker-compose up -d postgres-test
```
2. **Run Tests**:
```bash
# Automated (recommended)
./scripts/run-integration-tests.sh
# Manual
go test -tags=integration ./pkg/resolvespec ./pkg/restheadspec -v
```
3. **Stop PostgreSQL**:
```bash
make docker-down
# or
docker-compose down
```
### Setup without Docker
1. **Create Databases**:
```sql
CREATE DATABASE resolvespec_test;
CREATE DATABASE restheadspec_test;
```
2. **Set Environment Variable**:
```bash
export TEST_DATABASE_URL="host=localhost user=postgres password=yourpass dbname=resolvespec_test port=5432 sslmode=disable"
```
3. **Run Tests**:
```bash
go test -tags=integration ./pkg/resolvespec -v
# For restheadspec, update dbname in TEST_DATABASE_URL
export TEST_DATABASE_URL="host=localhost user=postgres password=yourpass dbname=restheadspec_test port=5432 sslmode=disable"
go test -tags=integration ./pkg/restheadspec -v
```
### Integration Test Coverage
#### pkg/resolvespec (7 tests)
- ✅ Create operation
- ✅ Read operation with pagination
- ✅ Read with filters (age > 25)
- ✅ Update operation
- ✅ Delete operation
- ✅ Metadata retrieval
- ✅ Read with relationship preloading
#### pkg/restheadspec (10 tests)
- ✅ GET all records
- ✅ GET with header-based filters
- ✅ GET with pagination (limit/offset)
- ✅ GET with sorting
- ✅ GET with column selection
- ✅ GET with relationship preloading
- ✅ Metadata endpoint
- ✅ OPTIONS/CORS handling
- ✅ Query params override headers
- ✅ GET single record by ID
## Test Coverage
### Generate Coverage Reports
```bash
# Unit test coverage
make coverage
# Integration test coverage
make coverage-integration
# Both
make coverage && make coverage-integration
```
Coverage reports are generated as HTML files:
- `coverage.html` - Unit tests
- `coverage-integration.html` - Integration tests
### View Coverage
```bash
# Open in browser
open coverage.html # macOS
xdg-open coverage.html # Linux
start coverage.html # Windows
```
## Makefile Commands
```bash
make help # Show all available commands
make test-unit # Run unit tests
make test-integration # Run integration tests (requires PostgreSQL)
make test # Run all tests
make docker-up # Start PostgreSQL
make docker-down # Stop PostgreSQL
make test-integration-docker # Full automated integration test
make clean # Clean up Docker volumes
make coverage # Generate unit test coverage
make coverage-integration # Generate integration test coverage
```
## CI/CD
### GitHub Actions Example
See `INTEGRATION_TESTS.md` for a complete GitHub Actions workflow example.
Key points:
- Use PostgreSQL service container
- Run unit tests first (faster)
- Run integration tests separately
- Generate coverage reports
- Upload coverage to codecov/coveralls
### GitLab CI Example
```yaml
stages:
- test
unit-tests:
stage: test
script:
- go test ./pkg/resolvespec ./pkg/restheadspec -v -cover
integration-tests:
stage: test
services:
- postgres:15
variables:
POSTGRES_DB: resolvespec_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
TEST_DATABASE_URL: "host=postgres user=postgres password=postgres dbname=resolvespec_test port=5432 sslmode=disable"
script:
- go test -tags=integration ./pkg/resolvespec ./pkg/restheadspec -v
```
## Troubleshooting
### Tests Won't Run
**Problem**: `go test` finds no tests
**Solution**: Make sure you're using the `-tags=integration` flag for integration tests
```bash
# Wrong (for integration tests)
go test ./pkg/resolvespec -v
# Correct
go test -tags=integration ./pkg/resolvespec -v
```
### Database Connection Failed
**Problem**: "connection refused" or "database does not exist"
**Solutions**:
1. Check PostgreSQL is running: `docker-compose ps`
2. Verify databases exist: `docker-compose exec postgres-test psql -U postgres -l`
3. Check environment variable: `echo $TEST_DATABASE_URL`
4. Recreate databases: `make clean && make docker-up`
### Permission Denied on Script
**Problem**: `./scripts/run-integration-tests.sh: Permission denied`
**Solution**:
```bash
chmod +x scripts/run-integration-tests.sh
```
### Tests Pass Locally but Fail in CI
**Possible causes**:
1. Different PostgreSQL version
2. Missing environment variables
3. Timezone differences
4. Race conditions (use `-race` flag to detect)
```bash
go test -race -tags=integration ./pkg/resolvespec -v
```
## Best Practices
1. **Run unit tests frequently** - They're fast and catch most issues
2. **Run integration tests before commits** - Ensures DB operations work
3. **Keep tests independent** - Each test should clean up after itself
4. **Use descriptive test names** - `TestIntegration_GetUsersWithFilters` vs `TestGet`
5. **Test error cases** - Not just the happy path
6. **Mock external dependencies** - Use interfaces for testability
7. **Maintain test data** - Keep test fixtures small and focused
## Test Data
Integration tests use these models:
- **TestUser**: id, name, email, age, active, posts[]
- **TestPost**: id, user_id, title, content, published, comments[]
- **TestComment**: id, post_id, content
Sample test data:
- 3 users (John Doe, Jane Smith, Bob Johnson)
- 3 posts (2 by John, 1 by Jane)
- 3 comments (2 on first post, 1 on second)
## Performance
- **Unit tests**: ~0.003s per package
- **Integration tests**: ~0.5-2s per package (depends on database)
- **Total**: <10 seconds for all tests
## Additional Resources
- [Go Testing Documentation](https://golang.org/pkg/testing/)
- [Table Driven Tests](https://github.com/golang/go/wiki/TableDrivenTests)
- [GORM Testing](https://gorm.io/docs/testing.html)
- [Integration Tests Guide](./INTEGRATION_TESTS.md)