Skip to content

Latest commit

 

History

History
1017 lines (829 loc) · 45.7 KB

File metadata and controls

1017 lines (829 loc) · 45.7 KB

SourceFlow.Net Cloud Integration Testing

This document provides an overview of the comprehensive testing framework for SourceFlow's AWS cloud integration, covering property-based testing, performance validation, security testing, and resilience patterns.

Overview

SourceFlow.Net includes a sophisticated testing framework that validates AWS cloud integration across multiple dimensions:

  • Functional Correctness - Property-based testing ensures universal correctness properties with 16 comprehensive properties
  • Performance Validation - Comprehensive benchmarking of cloud service performance with BenchmarkDotNet
  • Security Testing - Validation of encryption, authentication, and access control with IAM and KMS
  • Resilience Testing - Circuit breakers, retry policies, and failure handling with comprehensive fault injection
  • Local Development - Emulator-based testing for rapid development cycles with LocalStack
  • CI/CD Integration - Automated testing with resource provisioning and cleanup for continuous validation

Implementation Status

🎉 AWS Cloud Integration Testing (Complete)

All phases of the AWS cloud integration testing framework have been successfully implemented:

  • Phase 1-3: Enhanced test infrastructure with LocalStack, resource management, and test environment abstractions
  • Phase 4-5: Comprehensive SQS and SNS integration tests with property-based validation
  • Phase 6: KMS encryption integration tests with round-trip, key rotation, and security validation
  • Phase 7: AWS health check integration tests for SQS, SNS, and KMS services
  • Phase 9: AWS performance testing with benchmarks for throughput, latency, and scalability
  • Phase 10: AWS resilience testing with circuit breakers, retry policies, and failure handling
  • Phase 11: AWS security testing with IAM, encryption in transit, and audit logging validation
  • Phase 12-15: CI/CD integration, comprehensive documentation, and final validation

Key Achievements:

  • 16 property-based tests validating universal correctness properties
  • 100+ integration tests covering all AWS services (SQS, SNS, KMS)
  • Comprehensive performance benchmarks with BenchmarkDotNet
  • Full security validation including IAM, KMS, and audit logging
  • Complete CI/CD integration with automated resource provisioning
  • Extensive documentation for setup, execution, and troubleshooting
  • Enhanced wildcard permission validation logic
  • Supports scenarios with zero wildcards or controlled wildcard usage
  • Validates least privilege principles with realistic constraints

Testing Architecture

Test Project Structure

tests/
├── SourceFlow.Core.Tests/                # Core framework tests
│   ├── Unit/                             # Unit tests (Category=Unit)
│   └── Integration/                      # Integration tests
├── SourceFlow.Stores.EntityFramework.Tests/ # EF persistence tests
│   ├── Unit/                             # Unit tests (Category=Unit)
│   └── E2E/                             # Integration tests (Category=Integration)
├── SourceFlow.Cloud.AWS.Tests/           # AWS-specific testing
│   ├── Unit/                             # Unit tests with mocks
│   ├── Integration/                      # LocalStack integration tests
│   ├── Performance/                      # BenchmarkDotNet performance tests
│   ├── Security/                         # IAM and KMS security tests
│   ├── Resilience/                       # Circuit breaker and retry tests
│   └── E2E/                             # End-to-end scenario tests

Test Categorization

All test projects use xUnit [Trait("Category", "...")] attributes for filtering:

  • Category=Unit - Fast, isolated unit tests with no external dependencies
  • Category=Integration - Integration tests requiring databases or external services
  • Category=RequiresLocalStack - AWS integration tests requiring LocalStack container

Test Filtering Examples:

# Run only unit tests (fast feedback)
dotnet test --filter "Category=Unit"

# Run integration tests
dotnet test --filter "Category=Integration"

# Run security tests
dotnet test --filter "Category=Security"

# Run AWS integration tests with LocalStack
dotnet test --filter "Category=Integration&Category=RequiresLocalStack"

# Run all tests except LocalStack tests
dotnet test --filter "Category!=RequiresLocalStack"

# Run all tests except integration and security tests (CI pattern)
dotnet test --filter "FullyQualifiedName!~Integration&FullyQualifiedName!~Security"

Testing Frameworks and Tools

Property-Based Testing

  • FsCheck - Generates randomized test data to validate universal properties
  • 100+ iterations per property test for comprehensive coverage
  • Custom generators for cloud service configurations
  • Automatic shrinking to find minimal failing examples

Performance Testing

  • BenchmarkDotNet - Precise micro-benchmarking with statistical analysis
  • Memory diagnostics - Allocation tracking and GC pressure analysis
  • Throughput measurement - Messages per second across cloud services
  • Latency analysis - End-to-end processing times with percentile reporting

Integration Testing

  • LocalStack - AWS service emulation for local development
  • TestContainers - Automated container lifecycle management
  • Real cloud services - Validation against actual AWS services

Key Testing Scenarios

AWS Cloud Integration Testing

SQS Command Dispatching

  • FIFO Queue Testing - Message ordering and deduplication
  • Standard Queue Testing - High-throughput message delivery
  • Dead Letter Queue Testing - Failed message handling and recovery
  • Batch Operations - Efficient bulk message processing
  • Message Attributes - Metadata preservation and routing

SNS Event Publishing

  • Topic Publishing - Event distribution to multiple subscribers
  • Fan-out Messaging - Delivery to SQS, Lambda, and HTTP endpoints
  • Message Filtering - Subscription-based selective delivery
  • Correlation Tracking - End-to-end message correlation
  • Error Handling - Failed delivery retry mechanisms

KMS Encryption

  • Round-trip Encryption - Message encryption and decryption validation
  • Key Rotation - Seamless key rotation without service interruption
  • Sensitive Data Masking - Automatic masking of sensitive properties
  • Performance Impact - Encryption overhead measurement

Property-Based Testing Properties

The testing framework validates these universal correctness properties:

AWS Properties (16 Implemented)

  1. SQS Message Processing Correctness - Commands delivered with proper attributes and ordering
  2. SQS Dead Letter Queue Handling - Failed messages captured with complete metadata
  3. SNS Event Publishing Correctness - Events delivered to all subscribers with fan-out
  4. SNS Message Filtering and Error Handling - Subscription filters and error handling work correctly
  5. KMS Encryption Round-Trip Consistency - Encryption/decryption preserves message integrity
    • Property test validates: decrypt(encrypt(plaintext)) == plaintext for all inputs
    • Ensures encryption non-determinism (different ciphertext for same plaintext)
    • Verifies sensitive data protection (plaintext not visible in ciphertext)
    • Validates performance characteristics (encryption/decryption within bounds)
    • Tests Unicode safety and base64 encoding correctness
    • Implemented in: KmsEncryptionRoundTripPropertyTests.cs with 100+ test iterations
    • Integration tests complete: Comprehensive test suite in KmsEncryptionIntegrationTests.cs
      • End-to-end encryption/decryption with various message types
      • Algorithm validation (AES-256-GCM with envelope encryption)
      • Encryption context and AAD (Additional Authenticated Data) validation
      • Performance testing with different message sizes and concurrent operations
      • Data key caching performance improvements
      • Error handling for invalid ciphertext and corrupted envelopes
  6. KMS Key Rotation Seamlessness - Seamless key rotation without service interruption
    • Property test validates: messages encrypted with old keys decrypt after rotation
    • Ensures backward compatibility with previous key versions
    • Verifies automatic key version management
    • Tests rotation monitoring and alerting
    • Implemented in: KmsKeyRotationPropertyTests.cs and KmsKeyRotationIntegrationTests.cs
  7. KMS Security and Performance - Sensitive data masking and performance validation
    • Property test validates: [SensitiveData] attributes properly masked in logs
    • Ensures encryption performance within acceptable bounds
    • Verifies IAM permission enforcement
    • Tests audit logging and compliance
    • Implemented in: KmsSecurityAndPerformancePropertyTests.cs and KmsSecurityAndPerformanceTests.cs
  8. AWS Health Check Accuracy - Health checks reflect actual service availability
    • Property test validates: health checks accurately detect service availability, accessibility, and permissions
    • Ensures health checks complete within acceptable latency (< 5 seconds)
    • Verifies reliability under concurrent access (90%+ consistency)
    • Tests SQS queue existence, accessibility, send/receive permissions
    • Tests SNS topic availability, attributes, publish permissions, subscription status
    • Tests KMS key accessibility, encryption/decryption permissions, key status
    • Implemented in: AwsHealthCheckPropertyTests.cs and AwsHealthCheckIntegrationTests.cs
  9. AWS Performance Measurement Consistency - Reliable performance metrics across test runs
    • Property test validates: performance measurements are consistent within acceptable variance
    • Ensures throughput measurements are reliable across iterations
    • Verifies latency measurements under various load conditions
    • Tests resource utilization tracking accuracy
    • Implemented in: AwsPerformanceMeasurementPropertyTests.cs
  10. LocalStack AWS Service Equivalence - LocalStack provides equivalent functionality to AWS
  11. AWS Resilience Pattern Compliance - Circuit breakers, retry policies work correctly
    • Property test validates: circuit breakers open on failures and close on recovery
    • Ensures retry policies implement exponential backoff with jitter
    • Verifies maximum retry limits are enforced
    • Tests graceful handling of service throttling
    • Implemented in: AwsResiliencePatternPropertyTests.cs and resilience integration tests
  12. AWS Dead Letter Queue Processing - Failed message analysis and reprocessing
    • Property test validates: failed messages captured with complete metadata
    • Ensures message analysis and categorization work correctly
    • Verifies reprocessing capabilities and workflows
    • Tests monitoring and alerting integration
    • Implemented in: AwsDeadLetterQueuePropertyTests.cs and DLQ integration tests
  13. AWS IAM Security Enforcement - Proper authentication and authorization
    • Property test validates: IAM role assumption and credential management
    • Ensures least privilege access enforcement with flexible wildcard validation
    • Verifies cross-account access and permission boundaries
    • Tests IAM policy effectiveness and compliance
    • Enhanced Validation Logic: Handles property-based test generation edge cases
      • Lenient required permission validation when test generation produces more required permissions than available actions
      • Validates that granted actions include required permissions up to the available action count
      • Prevents false negatives from random test data generation
      • Supports zero wildcards or controlled wildcard usage (up to 50% of actions)
    • Implemented in: IamSecurityPropertyTests.cs and IamRoleTests.cs
  14. AWS Encryption in Transit - TLS encryption for all communications
  15. AWS Audit Logging - CloudTrail integration and event logging
  16. AWS CI/CD Integration Reliability - Tests run successfully in CI/CD with proper isolation

Performance Testing

Throughput Benchmarks

  • SQS Standard Queues - High-throughput message processing
  • SQS FIFO Queues - Ordered message processing performance
  • SNS Topic Publishing - Event publishing rates and fan-out performance

Latency Analysis

  • End-to-End Latency - Complete message processing times
  • Network Overhead - Cloud service communication latency
  • Encryption Overhead - Performance impact of message encryption
  • Serialization Impact - Message serialization/deserialization costs

Scalability Testing

  • Concurrent Connections - Performance under increasing load
  • Resource Utilization - Memory, CPU, and network usage
  • Service Limits - Behavior at cloud service limits
  • Auto-scaling - Performance during scaling events

Security Testing

Authentication and Authorization

  • AWS IAM Roles - Proper role assumption and credential management
  • Least Privilege - Access control enforcement testing
  • Cross-Account Access - Multi-account permission validation

Encryption Validation

  • AWS KMS - Message encryption with key rotation
  • Sensitive Data Masking - Automatic masking in logs
  • Encryption in Transit - TLS validation for all communications

Compliance Testing

  • Audit Logging - CloudTrail integration
  • Data Sovereignty - Regional data handling compliance
  • Security Standards - Validation against security best practices

Resilience Testing

Circuit Breaker Patterns

  • Failure Detection - Automatic circuit opening on service failures
  • Recovery Testing - Circuit closing on service recovery
  • Half-Open State - Gradual recovery validation
  • Configuration Testing - Threshold and timeout validation

Retry Policies

  • Exponential Backoff - Proper retry timing implementation
  • Jitter Implementation - Randomization to prevent thundering herd
  • Maximum Retry Limits - Proper retry limit enforcement
  • Poison Message Handling - Failed message isolation

Dead Letter Queue Processing

  • Failed Message Capture - Complete failure metadata preservation
  • Message Analysis - Failure pattern detection and categorization
  • Reprocessing Capabilities - Message recovery and retry workflows
  • Monitoring Integration - Alerting and operational visibility

Testing Bus Configuration

Overview

The Bus Configuration System requires testing at multiple levels to ensure routing is configured correctly and resources are created as expected.

Unit Testing Bus Configuration

Unit tests validate configuration without connecting to cloud services:

Testing Configuration Structure:

using SourceFlow.Cloud.Configuration;
using Xunit;

public class BusConfigurationTests
{
    [Fact]
    public void BusConfiguration_Should_Register_Command_Routes()
    {
        // Arrange
        var builder = new BusConfigurationBuilder();
        
        // Act
        var config = builder
            .Send
                .Command<CreateOrderCommand>(q => q.Queue("orders.fifo"))
                .Command<UpdateOrderCommand>(q => q.Queue("orders.fifo"))
            .Build();
        
        // Assert
        Assert.Equal(2, config.CommandRoutes.Count);
        Assert.Equal("orders.fifo", config.CommandRoutes[typeof(CreateOrderCommand)]);
        Assert.Equal("orders.fifo", config.CommandRoutes[typeof(UpdateOrderCommand)]);
    }
    
    [Fact]
    public void BusConfiguration_Should_Register_Event_Routes()
    {
        // Arrange
        var builder = new BusConfigurationBuilder();
        
        // Act
        var config = builder
            .Raise
                .Event<OrderCreatedEvent>(t => t.Topic("order-events"))
                .Event<OrderUpdatedEvent>(t => t.Topic("order-events"))
            .Build();
        
        // Assert
        Assert.Equal(2, config.EventRoutes.Count);
        Assert.Equal("order-events", config.EventRoutes[typeof(OrderCreatedEvent)]);
        Assert.Equal("order-events", config.EventRoutes[typeof(OrderUpdatedEvent)]);
    }
    
    [Fact]
    public void BusConfiguration_Should_Register_Listening_Queues()
    {
        // Arrange
        var builder = new BusConfigurationBuilder();
        
        // Act
        var config = builder
            .Listen.To
                .CommandQueue("orders.fifo")
                .CommandQueue("inventory.fifo")
            .Build();
        
        // Assert
        Assert.Equal(2, config.ListeningQueues.Count);
        Assert.Contains("orders.fifo", config.ListeningQueues);
        Assert.Contains("inventory.fifo", config.ListeningQueues);
    }
    
    [Fact]
    public void BusConfiguration_Should_Register_Topic_Subscriptions()
    {
        // Arrange
        var builder = new BusConfigurationBuilder();
        
        // Act
        var config = builder
            .Subscribe.To
                .Topic("order-events")
                .Topic("payment-events")
            .Build();
        
        // Assert
        Assert.Equal(2, config.SubscribedTopics.Count);
        Assert.Contains("order-events", config.SubscribedTopics);
        Assert.Contains("payment-events", config.SubscribedTopics);
    }
    
    [Fact]
    public void BusConfiguration_Should_Validate_Listening_Queue_Required_For_Subscriptions()
    {
        // Arrange
        var builder = new BusConfigurationBuilder();
        
        // Act & Assert
        var exception = Assert.Throws<InvalidOperationException>(() =>
            builder
                .Subscribe.To
                    .Topic("order-events")
                .Build());
        
        Assert.Contains("at least one command queue", exception.Message);
    }
}

Integration Testing with LocalStack

Integration tests validate Bus Configuration with LocalStack:

AWS Integration Test Example:

using SourceFlow.Cloud.AWS;
using Xunit;

public class AwsBusConfigurationIntegrationTests : IClassFixture<LocalStackFixture>
{
    private readonly LocalStackFixture _localStack;
    
    public AwsBusConfigurationIntegrationTests(LocalStackFixture localStack)
    {
        _localStack = localStack;
    }
    
    [Fact]
    public async Task Bootstrapper_Should_Create_SQS_Queues()
    {
        // Arrange
        var services = new ServiceCollection();
        services.UseSourceFlowAws(
            options => {
                options.ServiceUrl = _localStack.ServiceUrl;
                options.Region = RegionEndpoint.USEast1;
            },
            bus => bus
                .Send
                    .Command<CreateOrderCommand>(q => q.Queue("test-orders.fifo"))
                .Listen.To
                    .CommandQueue("test-orders.fifo"));
        
        var provider = services.BuildServiceProvider();
        
        // Act
        var bootstrapper = provider.GetRequiredService<IHostedService>();
        await bootstrapper.StartAsync(CancellationToken.None);
        
        // Assert
        var sqsClient = provider.GetRequiredService<IAmazonSQS>();
        var response = await sqsClient.GetQueueUrlAsync("test-orders.fifo");
        Assert.NotNull(response.QueueUrl);
        Assert.Contains("test-orders.fifo", response.QueueUrl);
    }
    
    [Fact]
    public async Task Bootstrapper_Should_Create_SNS_Topics()
    {
        // Arrange
        var services = new ServiceCollection();
        services.UseSourceFlowAws(
            options => {
                options.ServiceUrl = _localStack.ServiceUrl;
                options.Region = RegionEndpoint.USEast1;
            },
            bus => bus
                .Raise
                    .Event<OrderCreatedEvent>(t => t.Topic("test-order-events"))
                .Listen.To
                    .CommandQueue("test-orders"));
        
        var provider = services.BuildServiceProvider();
        
        // Act
        var bootstrapper = provider.GetRequiredService<IHostedService>();
        await bootstrapper.StartAsync(CancellationToken.None);
        
        // Assert
        var snsClient = provider.GetRequiredService<IAmazonSimpleNotificationService>();
        var topics = await snsClient.ListTopicsAsync();
        Assert.Contains(topics.Topics, t => t.TopicArn.Contains("test-order-events"));
    }
    
    [Fact]
    public async Task Bootstrapper_Should_Subscribe_Queues_To_Topics()
    {
        // Arrange
        var services = new ServiceCollection();
        services.UseSourceFlowAws(
            options => {
                options.ServiceUrl = _localStack.ServiceUrl;
                options.Region = RegionEndpoint.USEast1;
            },
            bus => bus
                .Listen.To
                    .CommandQueue("test-orders")
                .Subscribe.To
                    .Topic("test-order-events"));
        
        var provider = services.BuildServiceProvider();
        
        // Act
        var bootstrapper = provider.GetRequiredService<IHostedService>();
        await bootstrapper.StartAsync(CancellationToken.None);
        
        // Assert
        var snsClient = provider.GetRequiredService<IAmazonSimpleNotificationService>();
        var topics = await snsClient.ListTopicsAsync();
        var topicArn = topics.Topics.First(t => t.TopicArn.Contains("test-order-events")).TopicArn;
        
        var subscriptions = await snsClient.ListSubscriptionsByTopicAsync(topicArn);
        Assert.NotEmpty(subscriptions.Subscriptions);
        Assert.Contains(subscriptions.Subscriptions, s => s.Protocol == "sqs");
    }
}

Validation Strategies

Strategy 1: Configuration Snapshot Testing

Capture and compare Bus Configuration snapshots:

[Fact]
public void BusConfiguration_Should_Match_Expected_Snapshot()
{
    // Arrange
    var builder = new BusConfigurationBuilder();
    var config = builder
        .Send
            .Command<CreateOrderCommand>(q => q.Queue("orders.fifo"))
        .Raise
            .Event<OrderCreatedEvent>(t => t.Topic("order-events"))
        .Listen.To
            .CommandQueue("orders.fifo")
        .Subscribe.To
            .Topic("order-events")
        .Build();
    
    // Act
    var snapshot = config.ToSnapshot();
    
    // Assert
    var expected = LoadExpectedSnapshot("bus-configuration-v1.json");
    Assert.Equal(expected, snapshot);
}

Strategy 2: End-to-End Routing Validation

Test complete message flow through configured routing:

[Fact]
public async Task Message_Should_Flow_Through_Configured_Routes()
{
    // Arrange
    var services = ConfigureServicesWithBusConfiguration();
    var provider = services.BuildServiceProvider();
    
    // Start bootstrapper
    var bootstrapper = provider.GetRequiredService<IHostedService>();
    await bootstrapper.StartAsync(CancellationToken.None);
    
    // Act
    var commandBus = provider.GetRequiredService<ICommandBus>();
    var command = new CreateOrderCommand(new CreateOrderPayload { /* ... */ });
    await commandBus.PublishAsync(command);
    
    // Assert
    // Verify command was routed to correct queue
    // Verify event was published to correct topic
    // Verify listeners received messages
}

Strategy 3: Resource Existence Validation

Verify all configured resources exist after bootstrapping:

[Fact]
public async Task All_Configured_Resources_Should_Exist_After_Bootstrapping()
{
    // Arrange
    var services = ConfigureServicesWithBusConfiguration();
    var provider = services.BuildServiceProvider();
    var config = provider.GetRequiredService<BusConfiguration>();
    
    // Act
    var bootstrapper = provider.GetRequiredService<IHostedService>();
    await bootstrapper.StartAsync(CancellationToken.None);
    
    // Assert
    foreach (var queue in config.ListeningQueues)
    {
        var exists = await QueueExistsAsync(queue);
        Assert.True(exists, $"Queue {queue} should exist");
    }
    
    foreach (var topic in config.SubscribedTopics)
    {
        var exists = await TopicExistsAsync(topic);
        Assert.True(exists, $"Topic {topic} should exist");
    }
}

Best Practices for Testing Bus Configuration

  1. Use LocalStack for Integration Tests

    • LocalStack for AWS testing
    • Faster feedback than real cloud services
    • No cloud costs during development
  2. Test Configuration Validation

    • Verify invalid configurations throw exceptions
    • Test edge cases (empty queues, missing topics)
    • Validate required relationships (queue for subscriptions)
  3. Test Resource Creation Idempotency

    • Run bootstrapper multiple times
    • Verify no errors on repeated execution
    • Ensure resources aren't duplicated
  4. Test FIFO Queue Detection

    • Verify .fifo suffix enables sessions/FIFO
    • Test both FIFO and standard queues
    • Validate message ordering guarantees
  5. Mock Bootstrapper for Unit Tests

    • Test application logic without cloud dependencies
    • Mock IBusBootstrapConfiguration interface
    • Verify routing decisions without resource creation

Local Development Support

Emulator Integration

  • LocalStack - Complete AWS service emulation (SQS, SNS, KMS, IAM)
  • Container Management - Automatic lifecycle with TestContainers
  • Health Checking - Service availability validation
  • Smart Container Detection - Automatically detects and reuses existing LocalStack instances (e.g., in CI/CD environments) to avoid redundant container creation

Development Workflow

  • Fast Feedback - Rapid test execution without cloud dependencies
  • Cost Optimization - No cloud resource costs during development
  • Offline Development - Full functionality without internet connectivity
  • Debugging Support - Local service inspection and troubleshooting
  • CI/CD Efficiency - Seamlessly integrates with pre-configured LocalStack services in GitHub Actions and other CI platforms

CI/CD Integration

Automated Testing

  • Multi-Environment - Tests against both LocalStack and real AWS services
  • Resource Provisioning - Automatic cloud resource creation and cleanup via AwsResourceManager
  • Parallel Execution - Concurrent test execution for faster feedback
  • Test Isolation - Proper resource isolation to prevent interference with unique naming and tagging
  • Smart Container Management - Detects pre-existing LocalStack services in CI/CD environments (e.g., GitHub Actions service containers) and reuses them instead of creating redundant containers, improving test execution speed and resource efficiency
  • Adaptive Timeouts - Automatically adjusts LocalStack health check timeouts based on environment (90 seconds for CI, 30 seconds for local development)
  • Shared Container Fixtures - xUnit collection fixtures ensure single LocalStack instance per test run, preventing port conflicts in parallel test execution

GitHub Actions CI Optimizations

The test infrastructure includes specific optimizations for GitHub Actions CI environments:

LocalStack Service Container Integration:

  • Pre-Started Container - Release-CI workflow includes LocalStack as a service container
  • Port Mapping - LocalStack exposed on port 4566 for test access
  • Service Configuration - Configured with SQS, SNS, KMS, and IAM services
  • Health Checks - Container health validated before test execution begins
  • Automatic Lifecycle - GitHub Actions manages container startup and cleanup
  • Resource Efficiency - Single shared container across all test jobs
  • Fail-Fast Behavior - Tests fail immediately if LocalStack service container is not detected in CI (prevents Docker-in-Docker issues)
  • Anonymous Credentials - Uses AnonymousAWSCredentials to bypass credential validation in LocalStack (no dummy credentials needed)

LocalStack Timeout Handling:

  • Environment Detection - Automatically detects GitHub Actions via GITHUB_ACTIONS environment variable
  • Extended Timeouts - Uses 90-second health check timeout in CI (vs 30 seconds locally) to accommodate slower container initialization
  • Enhanced Retry Logic - Increases retry attempts (30 vs 15) and delays (3 seconds vs 2 seconds) for CI environments
  • External Instance Detection - 10-second timeout (vs 3 seconds locally) with 3 retry attempts to reliably detect pre-started LocalStack service containers
  • Lenient Detection - Accepts HTTP 200 from health endpoint even if services aren't fully initialized, deferring full readiness validation to main wait loop

Container Sharing:

  • xUnit Collection Fixtures - AwsIntegrationTestCollection enforces shared LocalStackTestFixture across all test classes
  • Port Conflict Prevention - Single LocalStack instance eliminates port 4566 allocation conflicts
  • Resource Efficiency - Reduces CI execution time by avoiding redundant container startups
  • CI Service Container Detection - In GitHub Actions, tests detect and reuse pre-started LocalStack service containers
  • Fail-Fast in CI - Tests fail immediately if LocalStack service container is not available in GitHub Actions (prevents Docker-in-Docker issues)
  • Local Development - Tests can start their own LocalStack containers when running locally

Configuration Classes:

  • LocalStackConfiguration.CreateForIntegrationTesting() - Returns CI-optimized configuration with 90-second timeout
  • LocalStackConfiguration.IsCI - Property that detects GitHub Actions environment
  • LocalStackManager.WaitForServicesAsync() - Adaptive retry logic based on environment detection

GitHub Actions Workflow Configuration:

The Release-CI workflow includes LocalStack as a service container with AWS credentials and simplified security settings for testing:

env:
  # AWS credentials for LocalStack (dummy values)
  AWS_ACCESS_KEY_ID: test
  AWS_SECRET_ACCESS_KEY: test
  AWS_DEFAULT_REGION: us-east-1

services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - 4566:4566
    env:
      SERVICES: sqs,sns,kms,iam
      DEBUG: 1
      DOCKER_HOST: unix:///var/run/docker.sock
      # Disable IAM enforcement for easier testing
      ENFORCE_IAM: 0
      # Skip SSL certificate validation
      SKIP_SSL_CERT_DOWNLOAD: 1
      # Disable signature validation (accept any credentials)
      DISABLE_CUSTOM_CORS_S3: 1
      DISABLE_CUSTOM_CORS_APIGATEWAY: 1
    options: >-
      --health-cmd "curl -f http://localhost:4566/_localstack/health || exit 1"
      --health-interval 10s
      --health-timeout 5s
      --health-retries 30
      --health-start-period 30s

AWS Credential Configuration:

The test infrastructure uses BasicAWSCredentials with dummy values for LocalStack testing. This approach provides better compatibility with AWS SDK endpoint resolution compared to AnonymousAWSCredentials.

// LocalStackTestFixture.cs
// Use BasicAWSCredentials with dummy values for LocalStack
// AnonymousAWSCredentials can cause issues with endpoint resolution
var credentials = new Amazon.Runtime.BasicAWSCredentials("test", "test");

var config = new Amazon.SQS.AmazonSQSConfig
{
    ServiceURL = LocalStackEndpoint,
    UseHttp = true,
    // Don't set RegionEndpoint when using ServiceURL - it can override the endpoint
    AuthenticationRegion = _configuration.Region.SystemName
};

Credential Configuration Details:

  • BasicAWSCredentials - Uses dummy "test"/"test" credentials for LocalStack
  • ServiceURL - Explicitly set to LocalStack endpoint (http://localhost:4566)
  • UseHttp - Enables HTTP instead of HTTPS for LocalStack
  • AuthenticationRegion - Set to match configured region (us-east-1)
  • No RegionEndpoint - Omitted when using ServiceURL to prevent endpoint override
  • No ForcePathStyle - Not required for LocalStack; ServiceURL configuration is sufficient

Benefits:

  • Endpoint Compatibility - BasicAWSCredentials works reliably with custom ServiceURL
  • LocalStack Support - Dummy credentials accepted by LocalStack without validation
  • Consistent Behavior - Same credential approach across all AWS service clients (SQS, SNS, KMS)
  • CI/CD Integration - Works seamlessly in GitHub Actions with LocalStack service containers
  • Local Development - No configuration needed for LocalStack testing

LocalStack Security Configuration:

  • ENFORCE_IAM: 0 - Disables IAM policy enforcement for simplified testing with dummy credentials
  • SKIP_SSL_CERT_DOWNLOAD: 1 - Skips SSL certificate downloads to speed up container initialization
  • DISABLE_CUSTOM_CORS_S3: 1 - Disables custom CORS for S3 (not used in tests but reduces overhead)
  • DISABLE_CUSTOM_CORS_APIGATEWAY: 1 - Disables custom CORS for API Gateway (not used in tests but reduces overhead)

These settings optimize LocalStack for CI testing by:

  • Accepting any AWS credentials (test/test) without validation
  • Reducing container startup time by skipping unnecessary downloads
  • Simplifying test execution without strict IAM policy enforcement
  • Maintaining functional equivalence for SQS, SNS, KMS, and IAM service testing

Service Container Benefits:

  • Container starts before test job begins
  • Health checks ensure services are ready before tests run
  • Automatic cleanup after job completion
  • No manual container management required in test code
  • Consistent environment across all CI runs

Reporting and Analysis

  • Comprehensive Reports - Detailed test results with metrics and analysis
  • Performance Trends - Historical performance tracking and regression detection
  • Security Validation - Security test results with compliance reporting
  • Failure Analysis - Actionable error messages with troubleshooting guidance

AWS Resource Management

AwsResourceManager (Implemented)

The AwsResourceManager provides comprehensive automated resource lifecycle management for AWS integration testing:

  • Resource Provisioning - Automatic creation of SQS queues, SNS topics, KMS keys, and IAM roles
  • CloudFormation Integration - Stack-based resource provisioning for complex scenarios
  • Resource Tracking - Automatic tagging and cleanup with unique test prefixes
  • Cost Estimation - Resource cost calculation and monitoring capabilities
  • Multi-Account Support - Cross-account resource management and cleanup
  • Test Isolation - Unique naming prevents conflicts in parallel test execution

LocalStack Manager (Implemented)

The LocalStackManager provides comprehensive container lifecycle management for AWS service emulation with enhanced features:

  • Smart Container Detection - Automatically detects and reuses existing LocalStack instances (e.g., in CI/CD environments) to avoid redundant container creation
  • Adaptive Timeout Configuration - Automatically adjusts health check timeouts based on environment (90 seconds for CI, 30 seconds for local development)
  • Health Endpoint Detection - Uses LocalStack's /_localstack/health endpoint for fast, reliable instance detection instead of attempting AWS service operations
  • Lenient Detection Strategy - Accepts HTTP 200 responses from health endpoint even if services aren't fully initialized, deferring full service readiness validation to the main wait loop
  • Retry Logic - Configurable retry attempts with delays for reliable external instance detection (3 attempts with 2-second delays)
  • Port Management - Automatic port conflict detection and resolution
  • Service Validation - Comprehensive AWS service emulation validation (SQS, SNS, KMS, IAM)
  • Diagnostic Logging - Detailed logging for troubleshooting container startup and service initialization issues

External Instance Detection Behavior:

  • Checks for existing LocalStack instances before starting new containers
  • Uses HTTP health endpoint (/_localstack/health) for faster detection than AWS SDK calls
  • Accepts HTTP 200 status code regardless of individual service status
  • Allows services to continue initializing after detection succeeds
  • Full service readiness validation occurs in WaitForServicesAsync with appropriate timeouts
  • Prevents port conflicts and reduces CI execution time by reusing pre-started containers
  • CI Fail-Fast: In GitHub Actions, tests fail immediately if LocalStack service container is not detected (prevents Docker-in-Docker issues)
  • Local Development: Tests can start their own LocalStack containers when no external instance is detected

CI/CD Optimizations:

  • Detects GitHub Actions environment via GITHUB_ACTIONS environment variable
  • Uses extended timeouts (10 seconds vs 3 seconds) for external instance detection in CI
  • Increases retry attempts and delays for slower CI environments
  • Adds initial delay after container start (5 seconds in CI, 2 seconds locally) for initialization scripts

Enhanced LocalStack container management with comprehensive AWS service emulation:

  • Service Emulation - Full support for SQS (standard and FIFO), SNS, KMS, and IAM
  • Health Checking - Service availability validation and readiness detection with adaptive timeouts
  • Port Management - Automatic port allocation and conflict resolution
  • Container Lifecycle - Automated startup, health checks, and cleanup
  • Service Validation - AWS SDK compatibility testing for each service
  • CI/CD Optimization - Detects pre-existing LocalStack instances (e.g., GitHub Actions services) to avoid redundant container creation
  • Environment-Aware Configuration - Automatically adjusts health check timeouts and retry logic for CI environments (90 seconds) vs local development (30 seconds)
  • Shared Container Support - xUnit collection fixtures ensure single LocalStack instance shared across all test classes to prevent port conflicts

AWS Test Environment (Implemented)

Comprehensive test environment abstraction supporting both LocalStack and real AWS:

  • Dual Mode Support - Seamless switching between LocalStack emulation and real AWS services
  • Resource Creation - FIFO queues, standard queues, SNS topics, KMS keys with proper configuration
  • Health Monitoring - Service-level health checks with response time tracking
  • Managed Identity - Support for IAM roles and credential management
  • Service Clients - Pre-configured SQS, SNS, KMS, and IAM clients

Key Features

  • Unique Naming - Test prefix-based resource naming to prevent conflicts
  • Automatic Cleanup - Comprehensive resource cleanup to prevent cost leaks
  • Resource Tagging - Metadata tagging for identification and cost allocation
  • Health Monitoring - Resource availability and permission validation
  • Batch Operations - Efficient bulk resource creation and deletion

Usage Example

var resourceManager = serviceProvider.GetRequiredService<IAwsResourceManager>();
var resourceSet = await resourceManager.CreateTestResourcesAsync("test-prefix", 
    AwsResourceTypes.SqsQueues | AwsResourceTypes.SnsTopics);

// Use resources for testing
// ...

// Automatic cleanup
await resourceManager.CleanupResourcesAsync(resourceSet);

Getting Started

Prerequisites

  • .NET 9.0 SDK or later
  • Docker Desktop for LocalStack support
  • AWS CLI (optional, for real AWS testing)

Running Tests

# Run all tests
dotnet test

# Run only unit tests (fast feedback, no external dependencies)
dotnet test --filter "Category=Unit"

# Run integration tests
dotnet test --filter "Category=Integration"

# Run AWS integration tests with LocalStack
dotnet test --filter "Category=Integration&Category=RequiresLocalStack"

# Run specific test categories
dotnet test --filter "Category=Performance"
dotnet test --filter "Category=Security"
dotnet test --filter "Category=Property"

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"

Configuration

Tests can be configured via appsettings.json or environment variables:

Configuration File (appsettings.json):

{
  "CloudIntegrationTests": {
    "UseEmulators": true,
    "RunPerformanceTests": false,
    "RunSecurityTests": true,
    "Aws": {
      "UseLocalStack": true,
      "Region": "us-east-1"
    }
  }
}

Environment Variables:

The test infrastructure supports configuration via environment variables for CI/CD integration:

Variable Purpose Default Example
AWS_ACCESS_KEY_ID AWS access key for LocalStack test test
AWS_SECRET_ACCESS_KEY AWS secret key for LocalStack test test
AWS_DEFAULT_REGION AWS region for testing us-east-1 us-east-1
GITHUB_ACTIONS Detects CI environment (none) true

Credential Resolution:

The AwsTestConfiguration class automatically resolves credentials in the following order:

  1. Environment Variables - Checks AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
  2. Default Values - Falls back to "test"/"test" for local development

This approach provides:

  • CI/CD Compatibility - Works seamlessly with GitHub Actions and other CI systems
  • Local Development - No configuration needed for LocalStack testing
  • Flexibility - Override credentials via environment variables when needed
  • Security - Credentials managed through CI/CD secrets, not hardcoded

Best Practices

Test Design

  • Property-based testing for universal correctness validation
  • Unit tests for specific scenarios and edge cases
  • Integration tests for end-to-end validation
  • Performance tests for scalability and optimization

Cloud Resource Management

  • Unique naming with test prefixes to prevent conflicts
  • Automatic cleanup to prevent resource leaks and costs
  • Resource tagging for identification and cost tracking
  • Least privilege access for security testing

Performance Testing

  • Baseline establishment for regression detection
  • Multiple iterations for statistical significance
  • Environment consistency for reliable measurements
  • Resource monitoring during test execution

Troubleshooting

Common Issues

LocalStack Container Startup Failures

  • Symptom: Tests fail with "LocalStack services did not become ready within timeout"
  • Cause: Container startup slower than expected, especially in CI environments
  • Solution:
    • Verify Docker Desktop is running and has sufficient resources
    • Check that GITHUB_ACTIONS environment variable is set correctly in CI
    • Ensure health check timeout is appropriate for environment (90s for CI, 30s for local)
    • Review LocalStack logs for service initialization errors

LocalStack Service Container Not Detected in CI

  • Symptom: Tests fail with "LocalStack service container not detected in GitHub Actions CI"
  • Cause: GitHub Actions workflow missing services.localstack configuration
  • Solution:
    • Verify workflow YAML includes LocalStack service container definition
    • Check service container health checks are configured correctly
    • Ensure port 4566 is mapped correctly in service configuration
    • Review GitHub Actions logs to confirm service container started successfully
    • Note: Tests cannot start their own containers in CI due to Docker-in-Docker limitations

Port Conflicts

  • Symptom: Tests fail with "port is already allocated" or "address already in use"
  • Cause: Multiple test classes attempting to start separate LocalStack instances
  • Solution:
    • Verify AwsIntegrationTestCollection class exists with [CollectionDefinition] and ICollectionFixture<LocalStackTestFixture>
    • Ensure all integration test classes use [Collection("AWS Integration Tests")] attribute
    • Check that only one LocalStack container is running (use docker ps)

External LocalStack Detection Issues

  • Symptom: Tests start new LocalStack container despite existing instance
  • Cause: External instance detection timeout too short or instance not responding to health endpoint
  • Solution:
    • Increase external detection timeout (10 seconds recommended for CI)
    • Verify existing LocalStack instance is healthy and responding to /_localstack/health endpoint
    • Check network connectivity between test runner and LocalStack container
    • Review console output for health check diagnostic messages
    • Ensure LocalStack is accepting HTTP connections on port 4566

CI-Specific Timeout Issues

  • Symptom: Tests pass locally but timeout in GitHub Actions CI
  • Cause: CI environment has slower container initialization than local development
  • Solution:
    • Verify LocalStackConfiguration.IsCI correctly detects GitHub Actions environment
    • Ensure CreateForIntegrationTesting() returns 90-second timeout configuration
    • Check GitHub Actions runner has sufficient resources allocated
    • Review CI logs for container startup timing information

Debug Configuration

  • Detailed logging for test execution visibility
  • Service health checking for LocalStack availability
  • Resource inspection - Cloud service validation
  • Performance profiling for optimization opportunities
  • Environment detection - Verify CI vs local environment detection
  • Container inspection - Check LocalStack container status and logs with docker logs

Contributing

When adding new cloud integration tests:

  1. Follow existing patterns - Use established test structures and naming
  2. Include property tests - Add universal correctness properties
  3. Add performance benchmarks - Measure new functionality performance
  4. Document test scenarios - Provide clear test descriptions
  5. Ensure cleanup - Proper resource management and cleanup
  6. Update documentation - Keep guides current with new capabilities

Related Documentation


Document Version: 2.2
Last Updated: 2026-03-07
Covers: AWS cloud integration testing capabilities with GitHub Actions CI optimizations and environment variable credential configuration