Multi-Region E2E Testing Guide
Overview
Section titled “Overview”This guide provides comprehensive documentation for running and maintaining multi-region E2E tests in FinFocus. These tests validate cost calculations across different AWS regions (us-east-1, eu-west-1, ap-northeast-1). They ensure regional pricing differences are correctly reflected in both projected and actual cost calculations.
Table of Contents
Section titled “Table of Contents”- Quick Start
- Test Architecture
- Configuration
- Test Fixtures
- Running Tests
- Validation Strategy
- Failure Handling
- Troubleshooting
- Extending Tests
- CI/CD Integration
Quick Start
Section titled “Quick Start”# Build the FinFocus binarymake build
# Run multi-region tests (default: us-east-1 only)make test-e2e
# Test all three regionsexport FINFOCUS_E2E_REGIONS="us-east-1,eu-west-1,ap-northeast-1"go test -v -tags e2e ./test/e2e -run TestMultiRegionExpected Duration: ~5 minutes per region (projected + actual costs)
Test Architecture
Section titled “Test Architecture”Components
Section titled “Components”Multi-region E2E tests consist of several key components:
-
Test Fixtures (
test/e2e/fixtures/multi-region/)- Pulumi programs for each region
- Expected cost data with tolerance ranges
- Region-specific configurations
-
Test Implementations (
test/e2e/multi_region_*_test.go)multi_region_projected_test.go: Projected cost validationmulti_region_actual_test.go: Actual cost validation with deployed resourcesmulti_region_fallback_test.go: Plugin fallback and error handling
-
Helper Functions (
test/e2e/multi_region_helpers.go)- Configuration management
- Cost validation logic
- Retry mechanisms
- Plugin version tracking
Test Flow
Section titled “Test Flow”┌─────────────────────────────────────────────────────────────┐│ 1. Setup & Configuration ││ - Load RegionTestConfig ││ - Validate region, tolerance, timeout ││ - Log plugin versions │└──────────────────────┬──────────────────────────────────────┘ │┌──────────────────────▼──────────────────────────────────────┐│ 2. Fixture Preparation ││ - Load expected costs from JSON ││ - Generate/use Pulumi plan ││ - Validate fixture structure │└──────────────────────┬──────────────────────────────────────┘ │┌──────────────────────▼──────────────────────────────────────┐│ 3. Cost Calculation ││ - Projected: Run finfocus cost projected ││ - Actual: Deploy resources + Run finfocus cost actual ││ - Parse JSON output │└──────────────────────┬──────────────────────────────────────┘ │┌──────────────────────▼──────────────────────────────────────┐│ 4. Validation ││ - Compare actual vs expected costs ││ - Check tolerance (±5% default) ││ - Validate plugin loading ││ - Record results │└──────────────────────┬──────────────────────────────────────┘ │┌──────────────────────▼──────────────────────────────────────┐│ 5. Assertion & Reporting ││ - Assert all validations passed ││ - Log execution time ││ - Report failures with context │└─────────────────────────────────────────────────────────────┘Configuration
Section titled “Configuration”Environment Variables
Section titled “Environment Variables”| Variable | Default | Description | Example |
|---|---|---|---|
FINFOCUS_E2E_REGIONS | us-east-1 | Comma-separated list of regions to test | us-east-1,eu-west-1,ap-northeast-1 |
FINFOCUS_E2E_TOLERANCE | 0.05 | Cost variance tolerance (±5%) | 0.10 for ±10% |
FINFOCUS_E2E_TIMEOUT | 10m | Maximum test execution time per region | 15m |
FINFOCUS_E2E_SKIP_ACTUAL_COSTS | false | Skip actual cost tests | true |
FINFOCUS_E2E_SKIP_DEPENDENCY_CHECK | false | Skip dependency validation | true |
AWS_PROFILE | (none) | AWS credentials profile to use | finfocus-testing |
AWS_REGION | (none) | Default AWS region for credentials | us-east-1 |
RegionTestConfig Structure
Section titled “RegionTestConfig Structure”type RegionTestConfig struct { Region string // AWS region code FixturePath string // Path to Pulumi program ExpectedCostsPath string // Path to expected-costs.json Tolerance float64 // Cost variance tolerance Timeout time.Duration // Maximum execution time PluginVersion string // Expected plugin version}Test Fixtures
Section titled “Test Fixtures”Directory Structure
Section titled “Directory Structure”test/e2e/fixtures/multi-region/├── us-east-1/│ ├── Pulumi.yaml # YAML runtime with inline resources (8 resources)│ └── expected-costs.json # Expected cost ranges├── eu-west-1/│ ├── Pulumi.yaml # YAML runtime (region: eu-west-1)│ └── expected-costs.json├── ap-northeast-1/│ ├── Pulumi.yaml # YAML runtime (region: ap-northeast-1)│ └── expected-costs.json└── unified/ # User Story 4 - Multi-region in single fixture ├── Pulumi.yaml # YAML runtime with explicit provider aliases └── expected-costs.json # Per-resource + aggregate cost expectationsResource Distribution
Section titled “Resource Distribution”Each region fixture includes:
- 2x EC2 Instances (t3.micro, t3.small) - Compute
- Different instance types to test pricing variations
- 2x EBS Volumes (gp3 100GB, io2 50GB) - Storage
- Different volume types and IOPS configurations
- 2x Network Resources (NAT Gateway, VPC Endpoint) - Network
- Regional network pricing differences
- 2x RDS Instances (db.t3.micro PostgreSQL, MySQL) - Database
- Database engine pricing variations
Total: 8 resources per region × 3 regions = 24 resources validated
Expected Costs Format
Section titled “Expected Costs Format”expected-costs.json structure:
{ "region": "us-east-1", "cost_type": "projected", "resources": [ { "resource_type": "aws:ec2:Instance", "resource_name": "web-server-t3-micro", "min_cost": 6.5, "max_cost": 7.5, "region": "us-east-1", "cost_type": "projected" }, ... ]}Running Tests
Section titled “Running Tests”Basic Usage
Section titled “Basic Usage”# Run all E2E tests (includes multi-region)make test-e2e
# Run only multi-region testsgo test -v -tags e2e ./test/e2e -run TestMultiRegion
# Run specific region testgo test -v -tags e2e ./test/e2e -run TestMultiRegion_Projected_USEast1Advanced Usage
Section titled “Advanced Usage”# Test all three regions with custom toleranceexport FINFOCUS_E2E_REGIONS="us-east-1,eu-west-1,ap-northeast-1"export FINFOCUS_E2E_TOLERANCE=0.10go test -v -tags e2e ./test/e2e -run TestMultiRegion
# Skip actual cost tests (for development)export FINFOCUS_E2E_SKIP_ACTUAL_COSTS=truego test -v -tags e2e ./test/e2e -run TestMultiRegion_Projected
# Run with increased timeoutexport FINFOCUS_E2E_TIMEOUT=15mgo test -timeout 20m -v -tags e2e ./test/e2e -run TestMultiRegion
# Run specific test suitego test -v -tags e2e ./test/e2e -run TestMultiRegion_FallbackParallel Execution
Section titled “Parallel Execution”Tests are designed to run in parallel for faster execution:
# Run with parallelism (default behavior)go test -v -tags e2e -parallel 3 ./test/e2e -run TestMultiRegion_ProjectedValidation Strategy
Section titled “Validation Strategy”Tolerance-Based Validation
Section titled “Tolerance-Based Validation”Multi-region tests use tolerance-based validation to handle pricing variability:
- Expected Cost Range: Each resource has
min_costandmax_costvalues - Default Tolerance: ±5% to accommodate minor pricing fluctuations
- Validation Logic: Actual cost must fall within [min_cost, max_cost]
- Variance Calculation: Percentage difference from midpoint
midpoint := (expected.MinCost + expected.MaxCost) / 2withinTolerance := actual.MonthlyCost >= expected.MinCost && actual.MonthlyCost <= expected.MaxCostvariance := (actual.MonthlyCost - midpoint) / midpoint * 100Plugin Validation
Section titled “Plugin Validation”Tests validate plugin loading and versioning:
- Plugin Availability: Verify AWS plugin is loaded
- Version Check: Validate plugin version matches expected
- Binary Path: Confirm plugin binary exists at reported path
- Region-Specific: Check correct plugin is used for each region
Failure Handling
Section titled “Failure Handling”Error Classification
Section titled “Error Classification”Multi-region tests implement strict failure semantics:
| Error Type | Detection | Action | Retry |
|---|---|---|---|
| Missing Pricing Data | ”no pricing data” in error | Fail immediately | No |
| Network Failure | ”connection refused”, “timeout” | Retry 3x with backoff | Yes |
| Invalid Region | Region not in [us-east-1, eu-west-1, ap-northeast-1] | Fail immediately | No |
| Cost Out of Tolerance | Actual cost outside expected range | Record failure, continue | No |
Retry Logic
Section titled “Retry Logic”Network failures use exponential backoff:
attempt 1: 100ms delayattempt 2: 200ms delayattempt 3: 400ms delayfinal: fail with errorFallback Behavior
Section titled “Fallback Behavior”When region-specific plugins are unavailable:
- Detection: Plugin not found or fails to load
- Fallback: Use public pricing data (issue #24)
- Warning: Log fallback occurrence
- Validation: Use looser tolerance (±10% instead of ±5%)
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”1. Test Fails: “No pricing data available”
Section titled “1. Test Fails: “No pricing data available””Symptom:
FAIL: No pricing data available for eu-west-1/aws:ec2:InstanceCause: Plugin doesn’t have pricing data for the region
Solution:
# Verify plugin installation./bin/finfocus plugin list
# Install region-specific plugin if missing./bin/finfocus plugin install aws-public --version <version>2. Test Fails: “Network failure after 3 retries”
Section titled “2. Test Fails: “Network failure after 3 retries””Symptom:
FAIL: Network failure after 3 retries: connection refusedCause: Plugin gRPC communication failed
Solution:
- Check plugin process:
ps aux | grep finfocus-plugin - Verify no firewall blocking localhost
- Retry test (may be transient)
- Check plugin logs:
~/.finfocus/logs/
3. Cost Variance Exceeds Tolerance
Section titled “3. Cost Variance Exceeds Tolerance”Symptom:
FAIL: Resource web-server cost $58.50 outside expected range [$50.00, $55.00]Cause: AWS pricing changed or resource configuration differs
Solution:
- Verify pricing change on AWS pricing page
- Update
expected-costs.jsonwith new ranges - Temporarily increase tolerance:
export FINFOCUS_E2E_TOLERANCE=0.10
4. Test Timeout
Section titled “4. Test Timeout”Symptom:
panic: test timed out after 10m0sCause: Test execution exceeded timeout (likely actual cost tests)
Solution:
# Increase timeoutexport FINFOCUS_E2E_TIMEOUT=15mgo test -timeout 20m -tags e2e ./test/e2e -run TestMultiRegion
# Or skip actual cost testsexport FINFOCUS_E2E_SKIP_ACTUAL_COSTS=true5. Missing Dependencies (Issue #177 or #24)
Section titled “5. Missing Dependencies (Issue #177 or #24)”Symptom:
FAIL: Pulumi Automation API support required (issue #177)Cause: Test depends on incomplete feature
Solution:
- Check issue status:
gh issue view 177 - Skip actual cost tests:
export FINFOCUS_E2E_SKIP_ACTUAL_COSTS=true - Wait for dependency to merge
Extending Tests
Section titled “Extending Tests”Adding a New Region
Section titled “Adding a New Region”-
Create Fixture Directory:
Terminal window mkdir -p test/e2e/fixtures/multi-region/us-west-2 -
Create Pulumi YAML Program (
Pulumi.yaml):name: multi-region-test-us-west-2runtime: yamldescription: Multi-region E2E test fixture for us-west-2config:aws:region:value: us-west-2pulumi:tags:value:Environment: e2e-testManagedBy: finfocusTestSuite: multi-regionresources:# EC2 Instance exampleweb-server-t3-micro:type: aws:ec2:Instanceproperties:ami: ami-placeholder-us-west-2instanceType: t3.microtags:Name: web-server-t3-micro# Add additional resources as needed (2 EC2, 2 EBS, 2 Network, 2 RDS) -
Create Expected Costs (
expected-costs.json):{"region": "us-west-2","cost_type": "projected","resources": [...]} -
Add Test Function (in
multi_region_projected_test.go):func TestMultiRegion_Projected_USWest2(t *testing.T) {if shouldSkipRegion(t, "us-west-2") {t.Skip("Skipping us-west-2 test")}testMultiRegionProjected(t, "us-west-2")} -
Update Configuration Validation (in
multi_region_helpers.go):validRegions := []string{"us-east-1", "eu-west-1", "ap-northeast-1", "us-west-2"}
Adding New Resource Types
Section titled “Adding New Resource Types”-
Update Fixture (
test/e2e/fixtures/multi-region/<region>/Pulumi.yaml):# Add new resource (e.g., Lambda function)test-function:type: aws:lambda:Functionproperties:runtime: nodejs18.xhandler: index.handlerrole: ${test-role.arn}# ... other properties -
Update Expected Costs (
expected-costs.json):{"resource_type": "aws:lambda:Function","resource_name": "test-function","min_cost": 0.2,"max_cost": 0.3,"region": "us-east-1","cost_type": "projected"} -
Verify All Regions: Add the same resource to all region fixtures
Unified Multi-Region Fixtures (User Story 4)
Section titled “Unified Multi-Region Fixtures (User Story 4)”Unified Overview
Section titled “Unified Overview”In addition to per-region fixtures, the unified fixture tests a single Pulumi program that deploys resources across multiple regions - a common real-world pattern.
Structure
Section titled “Structure”name: multi-region-test-unifiedruntime: yaml
resources: # Explicit provider per region aws-us-east-1: type: pulumi:providers:aws properties: region: us-east-1
aws-eu-west-1: type: pulumi:providers:aws properties: region: eu-west-1
# Resources reference specific providers web-us-east-1: type: aws:ec2:Instance properties: ami: ami-placeholder instanceType: t3.micro options: provider: ${aws-us-east-1}
web-eu-west-1: type: aws:ec2:Instance properties: ami: ami-placeholder instanceType: t3.micro options: provider: ${aws-eu-west-1}Validation
Section titled “Validation”Unified fixtures validate:
- Per-resource costs reflect region-specific pricing
- Aggregate total equals sum of individual region costs within ±5% tolerance
- Region attribution from provider configuration in plan JSON
Running Unified Tests
Section titled “Running Unified Tests”go test -v -tags e2e ./test/e2e -run TestMultiRegion_Unified_ProjectedTroubleshooting Unified Fixtures
Section titled “Troubleshooting Unified Fixtures”1. Issue: “Region not detected for resource”
Section titled “1. Issue: “Region not detected for resource””- Ensure provider is explicitly declared with
regionproperty - Verify resource uses
options.providerto reference the provider - Check plan JSON contains provider URN with region
2. Issue: “Aggregate total outside tolerance”
Section titled “2. Issue: “Aggregate total outside tolerance””- Tolerance compounds: 3 resources at +5% each = ~+15% total
- Update
aggregate_validationbounds inexpected-costs.jsonif needed
CI/CD Integration
Section titled “CI/CD Integration”GitHub Actions
Section titled “GitHub Actions”Multi-region tests run automatically via make test-e2e:
- name: Run E2E Tests run: make test-e2e env: FINFOCUS_E2E_REGIONS: us-east-1 FINFOCUS_E2E_SKIP_ACTUAL_COSTS: true AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}Performance Considerations
Section titled “Performance Considerations”- Projected tests: ~2-3 minutes per region
- Actual tests: ~4-5 minutes per region (includes deployment)
- Parallel execution: Reduces total time by ~50%
- CI optimization: Run us-east-1 only by default, full multi-region on schedule
Failure Notification
Section titled “Failure Notification”Tests report failures with detailed context:
Cost validation failed for web-server-t3-micro: Actual: $58.50 Expected: [$50.00, $55.00] Variance: +15.00% Region: eu-west-1 Cost Type: projectedBest Practices
Section titled “Best Practices”- Regular Updates: Update
expected-costs.jsonwhen AWS pricing changes - Tolerance Adjustment: Use ±5% for normal tests, ±10% for fallback scenarios
- Fixture Maintenance: Keep fixtures synchronized across regions
- Dependency Tracking: Monitor issues #177 and #24 for test prerequisites
- Log Review: Check plugin version logs to verify correct plugin usage
- Performance Monitoring: Watch for tests exceeding 5-minute target
- Error Classification: Ensure errors are properly classified for correct retry behavior