AMTP Gateway Testing Guide
September 9, 2025 · View on GitHub
This document provides comprehensive information about testing the AMTP Gateway implementation.
Test Structure
The testing strategy follows Go best practices with a mix of unit tests, integration tests, and benchmarks.
Test Organization
agentry/
├── internal/
│ ├── types/
│ │ └── message_test.go # Message type validation tests
│ ├── validation/
│ │ └── validator_test.go # Request validation tests
│ ├── processing/
│ │ ├── processor_test.go # Message processing unit tests
│ │ ├── delivery_test.go # Delivery engine unit tests
│ │ └── test_utils.go # Shared test utilities
│ ├── server/
│ │ └── handlers_test.go # HTTP handler unit tests
│ └── errors/
│ └── errors_test.go # Error handling tests
├── pkg/
│ └── uuid/
│ └── uuidv7_test.go # UUID generation tests
├── tests/
│ ├── integration_test.go # End-to-end integration tests
│ └── helpers.go # Test helpers and builders
└── scripts/
└── run-tests.sh # Test runner script
Running Tests
Quick Test Run
# Run all tests
go test ./...
# Run tests with verbose output
go test -v ./...
# Run tests with coverage
go test -cover ./...
Using the Test Script
# Run comprehensive test suite
./scripts/run-tests.sh
The test script provides:
- ✅ Colored output for better readability
- 📊 Test coverage reporting
- 🏃 Benchmark execution
- 📈 Summary statistics
Package-Specific Tests
# Test specific packages
go test ./internal/processing -v
go test ./internal/server -v
go test ./tests -v
# Run benchmarks
go test ./internal/processing -bench=.
go test ./tests -bench=.
Test Categories
1. Unit Tests
Location: Alongside source code in *_test.go files
Purpose: Test individual components in isolation
Examples:
- Message validation logic
- UUID generation
- Error handling
- Processing algorithms
- Delivery mechanisms
Key Features:
- Mock dependencies for isolation
- Fast execution
- High code coverage
- Edge case testing
2. Integration Tests
Location: tests/integration_test.go
Purpose: Test complete request/response flows
Coverage:
- HTTP API endpoints
- Message lifecycle (send → process → deliver → status)
- Error handling across components
- Coordination types (parallel, sequential, conditional)
- Idempotency verification
Key Features:
- Real HTTP server testing
- End-to-end message flows
- Error scenario validation
- Performance benchmarking
3. Test Utilities
Location: tests/helpers.go and internal/processing/test_utils.go
Purpose: Provide reusable test infrastructure
Components:
- TestMessageBuilder: Fluent interface for creating test messages
- TestSendRequestBuilder: Builder for API requests
- TestDataGenerator: Random test data generation
- MockDiscovery: Mock DNS discovery service
- MockDeliveryEngine: Mock message delivery
- TestAssertions: Common validation helpers
Test Patterns and Best Practices
1. Test Message Creation
// Using the builder pattern
message := NewTestMessage().
WithSender("test@example.com").
WithRecipients("recipient1@test.com", "recipient2@test.com").
WithSubject("Test Message").
WithParallelCoordination(30).
Build()
2. Mock Usage
// Setup mocks
discovery := NewMockDiscovery()
discovery.SetCapabilities("test.com", &dns.AMTPCapabilities{
Version: "1.0",
Gateway: "https://test.com",
MaxSize: 10485760,
})
deliveryEngine := NewMockDeliveryEngine()
deliveryEngine.SetDeliveryResult("recipient@test.com", &DeliveryResult{
Status: types.StatusDelivered,
})
3. HTTP Testing
// Create test server
server := createTestServer(t)
defer server.Close()
// Make request
resp, err := http.Post(server.URL+"/v1/messages", "application/json", body)
4. Error Testing
// Test error scenarios
tests := []struct {
name string
request interface{}
expectedStatus int
expectedCode string
}{
{"Invalid JSON", "invalid json", 400, "INVALID_REQUEST_FORMAT"},
{"Missing Sender", request, 400, "VALIDATION_FAILED"},
}
Test Coverage
Current Coverage Areas
✅ Message Types and Validation
- Message structure validation
- Coordination configuration validation
- Schema format validation
- Size calculations
✅ Processing Engine
- Immediate path processing
- Coordination types (parallel, sequential, conditional)
- Idempotency checking
- Status tracking
- Error handling
✅ Delivery Engine
- HTTPS delivery
- Retry logic with exponential backoff
- Connection pooling
- Error classification
- Batch delivery
✅ HTTP Handlers
- Message sending endpoint
- Message retrieval
- Status queries
- Health checks
- Error responses
✅ Error Handling
- Error code standardization
- HTTP status mapping
- Error response formatting
- Retryable error classification
✅ Integration Flows
- Complete message lifecycle
- Multi-recipient scenarios
- Coordination patterns
- Error propagation
- Idempotency verification
Coverage Goals
- Unit Tests: >90% code coverage
- Integration Tests: All major user flows
- Error Scenarios: All error codes and edge cases
- Performance: Benchmark critical paths
Test Data and Fixtures
Valid Test Data
const (
ValidMessageID = "01234567-89ab-7def-8123-456789abcdef"
ValidIdempotencyKey = "01234567-89ab-4def-8123-456789abcdef"
ValidEmail = "test@example.com"
ValidSchema = "agntcy:commerce.order.v1"
)
var (
SimplePayload = json.RawMessage(`{"message": "Hello, World!"}`)
ComplexPayload = json.RawMessage(`{
"order_id": "order-123",
"customer": {"id": "cust-456", "name": "John Doe"},
"items": [{"id": "item-1", "quantity": 2, "price": 19.99}],
"total": 69.97
}`)
)
Random Data Generation
generator := NewTestDataGenerator()
email := generator.RandomEmail() // user123@example.com
emails := generator.RandomEmails(5) // []string{...}
subject := generator.RandomSubject() // "Important Update"
payload := generator.RandomPayload() // Random JSON
schema := generator.RandomSchema() // "agntcy:commerce.order.v1"
headers := generator.RandomHeaders() // map[string]interface{}
Performance Testing
Benchmarks
# Run all benchmarks
go test -bench=. ./...
# Run specific benchmarks
go test -bench=BenchmarkProcessMessage ./internal/processing
go test -bench=BenchmarkDeliverMessage ./internal/processing
go test -bench=BenchmarkIntegration ./tests
Benchmark Results
Typical performance characteristics:
- Message Processing: ~1ms per message (immediate path)
- HTTP Request Handling: ~2ms per request
- UUID Generation: ~100ns per UUID
- Message Validation: ~10μs per message
Continuous Integration
Test Pipeline
- Lint Check:
golangci-lint run - Unit Tests:
go test ./... -short - Integration Tests:
go test ./tests - Coverage Report:
go test -coverprofile=coverage.out ./... - Benchmark Regression:
go test -bench=. -benchmem
Quality Gates
- ✅ All tests must pass
- ✅ Code coverage >85%
- ✅ No linting errors
- ✅ Benchmark performance within 10% of baseline
Debugging Tests
Verbose Output
go test -v ./internal/processing
Specific Test
go test -run TestProcessMessage_ImmediatePath ./internal/processing
Debug with Delve
dlv test ./internal/processing -- -test.run TestProcessMessage_ImmediatePath
Test Logging
Tests use structured logging that can be enabled:
// In test setup
logger := logging.NewLogger(config.LoggingConfig{Level: "debug"})
Common Test Scenarios
1. Message Processing Flow
func TestMessageLifecycle(t *testing.T) {
// 1. Send message
// 2. Verify processing
// 3. Check delivery status
// 4. Validate final state
}
2. Error Handling
func TestErrorScenarios(t *testing.T) {
// 1. Invalid input
// 2. Processing failures
// 3. Delivery failures
// 4. Network errors
}
3. Coordination Patterns
func TestCoordinationTypes(t *testing.T) {
// 1. Parallel coordination
// 2. Sequential coordination
// 3. Conditional coordination
// 4. Mixed scenarios
}
4. Performance Testing
func BenchmarkHighLoad(b *testing.B) {
// 1. Setup test environment
// 2. Generate load
// 3. Measure performance
// 4. Validate results
}
Test Maintenance
Adding New Tests
- Identify test category (unit/integration)
- Choose appropriate location (alongside code or tests/)
- Use existing patterns (builders, mocks, helpers)
- Follow naming conventions (TestFunctionName_Scenario)
- Add to test script if needed
Updating Tests
- Keep tests in sync with code changes
- Update mocks when interfaces change
- Maintain test data validity
- Review coverage after changes
Test Documentation
- Document complex test scenarios
- Explain mock configurations
- Provide examples for new patterns
- Update this guide when adding new test types
Troubleshooting
Common Issues
- Import cycles: Use interfaces and dependency injection
- Flaky tests: Avoid time dependencies, use mocks
- Slow tests: Optimize setup, use parallel execution
- Coverage gaps: Add tests for uncovered branches
Test Failures
- Check error messages for specific failures
- Verify test data is still valid
- Review recent changes that might affect tests
- Run tests in isolation to identify conflicts
Future Enhancements
Planned Additions
- Load Testing: High-concurrency scenarios
- Chaos Testing: Network failures, service disruptions
- Contract Testing: API compatibility verification
- Security Testing: Authentication, authorization, input validation
- Performance Regression: Automated benchmark comparison
Test Infrastructure
- Test Containers: Database and external service testing
- Test Fixtures: Standardized test data sets
- Test Reporting: Enhanced metrics and dashboards
- Parallel Execution: Faster test runs
This testing guide ensures comprehensive coverage of the AMTP Gateway functionality while maintaining high code quality and performance standards.