Skip to content

test(integration-tests): add structured test infrastructure #781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

suchapalaver
Copy link
Collaborator

Integration Testing Infrastructure Improvement

Overview

This PR enhances the integration testing infrastructure for indexer-rs by introducing structured test contexts, reusable utilities, and improved error handling. The changes make tests more reliable, debuggable, and maintainable while preserving existing functionality.

Problem Statement

The current integration testing approach had several limitations:

  1. Monolithic test structure: Large end-to-end tests were difficult to debug when failing
  2. No test isolation: Tests could interfere with each other and state management was poor
  3. Limited error diagnostics: Generic error messages made debugging difficult
  4. No allocation lifecycle testing: Tests never closed allocations, preventing full RAV redemption flow testing
  5. Poor observability: Limited visibility into test state and system behavior during test execution

Solution

Phase 1: Foundation (Implemented)

1. Test Context and Isolation (test_context.rs)

Created a comprehensive TestContext struct that provides:

  • Unique test identifiers for isolation
  • Structured error types with detailed diagnostics
  • Automatic cleanup management
  • Test state tracking (allocations, escrow accounts)
  • Condition waiting utilities with timeouts

Key features:

pub struct TestContext {
    pub test_id: String,
    pub http_client: Arc<Client>,
    pub metrics_checker: MetricsChecker,
    pub wallet: PrivateKeySigner,
    pub cleanup_tasks: Vec<CleanupTask>,
    pub allocations: Vec<TestAllocation>,
    pub escrow_accounts: HashMap<Address, TestEscrowAccount>,
}

Structured error types for better diagnostics:

#[derive(Debug, thiserror::Error)]
pub enum TestError {
    #[error("Escrow insufficient: sender={sender}, required={required}, available={available}")]
    EscrowInsufficient { sender: Address, required: u128, available: u128 },
    
    #[error("Horizon detection failed: expected {expected_accounts} accounts, found {found_accounts}")]
    HorizonDetectionFailed { expected_accounts: usize, found_accounts: usize },
    // ... more specific error types
}

2. Reusable Test Utilities (test_utils.rs)

Extracted and enhanced utilities from existing tests:

  • ReceiptUtils: V1/V2 receipt creation, sending, and batch operations
  • EscrowUtils: Escrow balance checking and validation
  • ServiceUtils: Service health checking and monitoring
  • MetricsUtils: RAV generation and fee aggregation monitoring
  • TestAssertions: Enhanced assertions with better error messages

Key improvements:

  • Batch receipt sending with proper error handling
  • Timeout-based condition waiting
  • Service health monitoring
  • Metrics-based test verification

3. Test Macro for Consistent Structure

Introduced test_with_context! macro for consistent test structure:

test_with_context!(test_v2_receipt_processing, |ctx: &mut TestContext| async {
    // Test implementation with automatic cleanup
    let allocation = ctx.find_active_allocation().await?;
    let receipts_sent = ReceiptUtils::send_v2_receipt_batch(ctx, &allocation.id, 10, 1000, &payer, &service_provider).await?;
    TestAssertions::assert_receipts_accepted(receipts_sent, 10)?;
    Ok(())
});

Phase 2: Enhanced Test Coverage (Planned)

1. Allocation Lifecycle Testing

  • Allocation creation and management
  • Allocation closing and RAV redemption
  • Full lifecycle integration tests

2. Error Scenario Testing

  • Insufficient escrow balance scenarios
  • Invalid signature handling
  • Network partition recovery
  • Service failure scenarios

3. V1/V2 Migration Testing

  • Mixed V1/V2 environments
  • Migration period testing
  • Backward compatibility verification

Phase 3: Advanced Observability (Planned)

1. Test Observer Pattern

  • Comprehensive test state monitoring
  • Real-time metrics collection
  • Event-driven test verification

2. Performance Baseline Testing

  • Performance regression detection
  • Resource usage monitoring
  • Scalability testing

What This Enables

Enhanced Testing Capabilities

  1. Precise Error Diagnostics: Instead of generic failures, tests now provide specific error contexts:

    // Before: "Test failed"
    // After: "Horizon detection failed: expected 1 accounts, found 0"
  2. Test Isolation: Each test runs in its own isolated context with unique identifiers, preventing interference between tests running in parallel

  3. Automatic Cleanup: Tests automatically clean up resources (allocations, escrow funds) even when they fail

  4. Comprehensive Monitoring: Tests can monitor metrics, service health, and system state in real-time

  5. Batch Operations: Send multiple receipts efficiently with proper error handling and progress tracking

New Testing Workflow

1. Writing Tests with TestContext

test_with_context!(test_v2_receipts, |ctx: &mut TestContext| async {
    // Automatic setup and unique test ID
    let allocation = ctx.find_active_allocation().await?;
    
    // Send receipts with monitoring
    let successful = ReceiptUtils::send_v2_receipt_batch(
        ctx, &allocation.id, 10, 1000, &payer, &service_provider
    ).await?;
    
    // Structured assertions
    TestAssertions::assert_receipts_accepted(successful, 10)?;
    
    // Wait for processing with timeout
    MetricsUtils::wait_for_rav_generation(ctx, &allocation.id, 0, Duration::from_secs(30)).await?;
    
    // Automatic cleanup happens here
    Ok(())
});

2. Developer Workflow

Before (Old Approach):

  1. Write monolithic test function
  2. Manually handle setup/teardown
  3. Debug generic error messages
  4. Tests interfere with each other
  5. Limited observability into test state

After (New Approach):

  1. Use test_with_context! macro for consistent structure
  2. Leverage TestContext for automatic resource management
  3. Get detailed error diagnostics with context
  4. Tests run in isolation with unique IDs
  5. Monitor system state and metrics in real-time

3. Error Handling Workflow

// Detailed error context helps identify root causes
match result {
    Err(TestError::EscrowInsufficient { sender, required, available }) => {
        println!("❌ Escrow insufficient: sender={}, required={}, available={}", 
                 sender, required, available);
        // Can now take specific action based on error type
    }
    Err(TestError::HorizonDetectionFailed { expected_accounts, found_accounts }) => {
        println!("❌ Horizon mode not detected: expected {}, found {}", 
                 expected_accounts, found_accounts);
        // Specific debugging steps for Horizon issues
    }
    _ => // Handle other error types
}

4. CI/CD Integration

Prerequisites:

  • Tests require a running test environment (set up with just setup)
  • Local blockchain, graph-node, and indexer services must be running
  • Escrow accounts must be funded for both V1 and V2 testing

Test Execution:

  • Tests run in parallel safely due to isolation
  • Failures provide actionable error messages
  • Automatic cleanup prevents resource leaks
  • Metrics collection enables performance monitoring

Debugging Failed Tests:

  • Structured errors point to specific issues
  • Test IDs help correlate logs across services
  • Metrics snapshots show system state at failure time
  • Cleanup logs show what resources were involved

Benefits

For Developers

  1. Faster debugging: Structured errors and test context make failures easier to diagnose
  2. Better test isolation: Tests don't interfere with each other
  3. Reusable components: Common operations are extracted into utilities
  4. Consistent structure: All tests follow the same pattern
  5. Real-time monitoring: Watch system metrics and state during test execution

For CI/CD

  1. More reliable tests: Proper cleanup and isolation reduce flaky tests
  2. Better failure reporting: Detailed error messages help identify issues quickly
  3. Parallel test execution: Isolated tests can run in parallel safely
  4. Actionable diagnostics: Errors point to specific root causes

For System Reliability

  1. Comprehensive coverage: Tests cover both happy path and error scenarios
  2. Real-world simulation: Tests simulate actual usage patterns
  3. Performance monitoring: Baseline testing prevents regressions
  4. Resource management: Automatic cleanup prevents test pollution

Implementation Progress

✅ Completed

  • TestContext struct with isolation and cleanup
  • Structured error types for better diagnostics
  • test_utils.rs with extracted utilities
  • test_with_context! macro for consistent structure
  • Receipt batch operations with proper error handling
  • Service health monitoring utilities
  • Metrics-based test verification
  • Enhanced test examples demonstrating new capabilities
  • CLI integration with cargo run -- test-with-context command

🚧 In Progress

  • Integration with existing test suite
  • Migration of existing tests to new structure
  • Documentation updates

📋 Planned

  • Allocation lifecycle testing
  • Error scenario test coverage
  • Performance baseline establishment
  • Advanced observability features

Breaking Changes

None. The changes are purely additive and maintain backward compatibility with existing tests.

Testing

The new infrastructure has been tested with:

  • Test context creation and cleanup
  • Error type serialization and display
  • Utility function correctness
  • Macro expansion and compilation

Running the Enhanced Tests

  1. Set up the test environment:

    just setup
  2. Run the enhanced tests:

    cd integration-tests
    cargo run -- test-with-context
  3. Monitor test execution:

    • Test output shows detailed progress and diagnostics
    • Each test runs with a unique ID for isolation
    • Automatic cleanup occurs even if tests fail

Documentation

  • Comprehensive code documentation
  • Usage examples in code
  • Integration testing instructions updated

Next Steps

  1. Migrate existing tests to use the new infrastructure
  2. Implement allocation lifecycle testing for complete RAV flow
  3. Add comprehensive error scenario coverage
  4. Establish performance baselines for regression detection

@suchapalaver suchapalaver force-pushed the suchapalaver/test/enhance-integration-testing-infra branch from b799fe5 to 4eeb7f3 Compare July 18, 2025 20:06
Copy link
Contributor

github-actions bot commented Jul 18, 2025

Pull Request Test Coverage Report for Build 16443902871

Details

  • 0 of 661 (0.0%) changed or added relevant lines in 4 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-3.0%) to 71.638%

Changes Missing Coverage Covered Lines Changed/Added Lines %
integration-tests/src/main.rs 0 4 0.0%
integration-tests/src/test_context.rs 0 169 0.0%
integration-tests/src/enhanced_tests.rs 0 187 0.0%
integration-tests/src/test_utils.rs 0 301 0.0%
Totals Coverage Status
Change from base Build 16443576183: -3.0%
Covered Lines: 11816
Relevant Lines: 16494

💛 - Coveralls

@neithanmo
Copy link
Collaborator

Looking forward for this
That has everything and more that We envisioned at some point
The re usability and more control of allocations/collections would be a challenge
and for user an internal network and direct contract calls to the escrow/tap smart contracts programatically

excited for this!!!

@suchapalaver suchapalaver force-pushed the suchapalaver/test/enhance-integration-testing-infra branch from 4eeb7f3 to 17f0d90 Compare July 21, 2025 20:46
@suchapalaver suchapalaver force-pushed the suchapalaver/test/enhance-integration-testing-infra branch from 17f0d90 to 49537bd Compare July 22, 2025 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants