# Testing Guide
## Backend API Testing Documentation

This document describes the testing infrastructure for the SolaceScan backend.

---

## Test Structure

```
backend/
├── api/
│   ├── rest/
│   │   └── api_test.go          # REST API integration tests
│   └── track1/
│       ├── cache_test.go         # Cache unit tests
│       └── rate_limiter_test.go # Rate limiter unit tests
├── benchmarks/
│   └── benchmark_test.go        # Performance benchmarks
└── README_TESTING.md             # This file
```

---

## Running Tests

### Unit Tests

```bash
# Run all tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests with verbose output
go test -v ./...

# Run specific test
go test -v ./api/track1 -run TestInMemoryCache_GetSet
```

### Integration Tests

```bash
# Run integration tests (requires test database)
go test -tags=integration ./api/rest/...

# With database connection
DB_HOST=localhost DB_USER=test DB_PASSWORD=test DB_NAME=test go test -tags=integration ./api/rest/...
```

**Note:** The current `api/rest` tests run without a database and assert 200/503/404 as appropriate. For full integration tests against a real DB, set up a test database (e.g. Docker or testcontainers) and run the same suite with DB env vars; optional future improvement: add a build tag and testcontainers for CI.

### Benchmarks

```bash
# Run all benchmarks
go test -bench=. ./benchmarks/...

# Run specific benchmark
go test -bench=BenchmarkInMemoryCache_Get ./benchmarks/...

# With memory profiling
go test -bench=. -benchmem ./benchmarks/...
```

---

## Test Coverage

### Current Coverage

- ✅ Cache: Unit tests for in-memory cache
- ✅ Rate Limiter: Unit tests for in-memory rate limiter
- ✅ API Endpoints: Integration tests for REST API
- ⚠️ Database: Requires test database setup
- ⚠️ Redis: Requires Redis test instance

### Coverage Goals

- **Unit Tests**: 80%+ coverage
- **Integration Tests**: All critical paths
- **E2E Tests**: Core user flows

---

## Test Database Setup

### Option 1: Docker Test Database

```bash
# Start test database
docker run -d \
  --name test-postgres \
  -e POSTGRES_USER=test \
  -e POSTGRES_PASSWORD=test \
  -e POSTGRES_DB=test \
  -p 5433:5432 \
  postgres:16

# Run migrations
cd database/migrations
go run migrate.go --up

# Run tests
DB_HOST=localhost DB_PORT=5433 DB_USER=test DB_PASSWORD=test DB_NAME=test go test ./...
```

### Option 2: Local Test Database

```bash
# Create test database
createdb test_explorer

# Run migrations
cd database/migrations
go run migrate.go --up

# Run tests
DB_HOST=localhost DB_USER=postgres DB_NAME=test_explorer go test ./...
```

---

## Writing Tests

### Unit Test Example

```go
func TestInMemoryCache_GetSet(t *testing.T) {
    cache := gateway.NewInMemoryCache() // from github.com/explorer/backend/libs/go-rpc-gateway
    
    key := "test-key"
    value := []byte("test-value")
    ttl := 5 * time.Minute
    
    // Test Set
    err := cache.Set(key, value, ttl)
    require.NoError(t, err)
    
    // Test Get
    retrieved, err := cache.Get(key)
    require.NoError(t, err)
    assert.Equal(t, value, retrieved)
}
```

### Integration Test Example

```go
func TestListBlocks(t *testing.T) {
    _, mux := setupTestServer(t)
    
    req := httptest.NewRequest("GET", "/api/v1/blocks?limit=10&page=1", nil)
    w := httptest.NewRecorder()
    mux.ServeHTTP(w, req)
    
    assert.Equal(t, http.StatusOK, w.Code)
}
```

---

## Continuous Integration

### GitHub Actions Example

```yaml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
          POSTGRES_DB: test
        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: '1.21'
      - run: go test -v -cover ./...
```

---

## Best Practices

1. **Use Table-Driven Tests**: For multiple test cases
2. **Test Edge Cases**: Empty inputs, boundary values, errors
3. **Mock External Dependencies**: Database, Redis, RPC calls
4. **Clean Up**: Use `defer` for cleanup operations
5. **Parallel Tests**: Use `t.Parallel()` for independent tests
6. **Test Names**: Use descriptive names: `TestFunctionName_Scenario_ExpectedResult`

---

## Troubleshooting

### Tests Failing

1. **Check Database Connection**: Ensure test database is running
2. **Check Environment Variables**: Verify test configuration
3. **Check Test Isolation**: Ensure tests don't interfere with each other
4. **Check Logs**: Review test output for error messages

### Slow Tests

1. **Use Test Database**: Don't use production database
2. **Parallel Execution**: Enable `-parallel` flag
3. **Skip Integration Tests**: Use build tags to skip slow tests
4. **Mock External Services**: Don't make real network calls

---

**Last Updated**: $(date)
