Files
explorer-monorepo/backend/README_TESTING.md
2026-03-02 12:14:13 -08:00

5.0 KiB

Testing Guide

Backend API Testing Documentation

This document describes the testing infrastructure for the SolaceScanScout 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

# 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

# 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

# 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

# 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

# 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

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

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

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)