ADR-002: Integration Testing Strategy for E2E Workflows¶
Status: Accepted
Date: 2025-12-23
Authors: Development Team
Deciders: Core Development Team, Technical Lead
Context¶
The Prediction DAO Research platform consists of multiple interconnected smart contracts (FutarchyGovernor, WelfareMetricRegistry, ProposalRegistry, ConditionalMarketFactory, PrivacyCoordinator, OracleResolver, and RagequitModule) that must work together correctly to enable complete user workflows. While we have comprehensive unit tests for individual contracts, we lack integration tests to validate end-to-end (E2E) flows across contract boundaries.
Problem Statement¶
Without integration tests, we face several risks:
- Hidden Integration Bugs: Unit tests validate individual contracts but may miss issues in contract interactions, state synchronization, and event sequencing
- Manual Testing Burden: Developers must manually verify complete workflows, which is time-consuming and error-prone
- Regression Detection: Changes to one contract may break workflows involving other contracts, with no automated detection
- Deployment Confidence: Lack of E2E validation reduces confidence in production deployments
- Documentation Gap: No systematic documentation of expected E2E behaviors and workflows
Forces at Play¶
- Complexity: The system has 6 key E2E workflows with multiple contracts interacting in each
- Time Constraints: Need efficient test execution to maintain fast CI/CD pipeline
- Existing Infrastructure: Already using Hardhat with comprehensive unit tests
- Team Familiarity: Team is experienced with Hardhat and ethers.js
- Maintainability: Tests must be maintainable as contracts evolve
Decision¶
We will implement a comprehensive integration testing strategy using the Hardhat ecosystem with the following approach:
- Testing Framework: Use Hardhat Network with ethers.js v6, Chai matchers, and Hardhat Network Helpers
- Test Organization: Create separate
test/integration/directory structure organized by feature area (clearpath, fairwins, oracle, factory) - Fixture Pattern: Implement reusable deployment fixtures using
loadFixturefrom@nomicfoundation/hardhat-network-helpersfor efficient state management - Coverage Target: Achieve 100% coverage of the 6 key E2E workflows:
- Complete proposal lifecycle (ClearPath)
- Privacy-preserving trading flow
- Multi-stage oracle resolution
- Ragequit protection flow
- FairWins market creation and resolution
- DAO factory deployment flow
- CI/CD Integration: Add dedicated GitHub Actions workflow for integration tests with coverage reporting
- Helper Library: Create reusable helper functions for common multi-step operations
- Documentation: Maintain comprehensive integration testing plan document with examples and best practices
Rationale¶
Why Hardhat Ecosystem?¶
- Already in use: No new tooling to learn, leverages existing expertise
- Performance: Hardhat Network's in-memory blockchain provides fast test execution
- Debugging: Excellent debugging capabilities with console.log and stack traces
- Community standard: Industry best practice for Ethereum development
- Rich ecosystem: Network helpers, time manipulation, account impersonation all available
Why Separate Integration Tests?¶
- Clarity: Clear distinction between unit and integration tests
- Execution control: Can run integration tests separately (slower but more comprehensive)
- Organization: Feature-based organization matches user workflows
- Maintenance: Easier to locate and update tests related to specific flows
Why Fixture Pattern?¶
- Performance: Snapshot/restore is much faster than redeploying contracts for each test
- Consistency: Ensures all tests start from identical state
- Reusability: Single fixture can support multiple test suites
- Isolation: Tests remain independent without side effects
Why These 6 Workflows?¶
These workflows represent: - Critical paths: Most important user journeys through the system - Multi-contract interactions: Exercise integration points between contracts - Platform coverage: Cover both ClearPath (governance) and FairWins (markets) - Security-critical operations: Include oracle resolution, bond management, privacy
Consequences¶
Positive¶
- Higher quality: Early detection of integration issues before production
- Faster debugging: Failed tests pinpoint exact interaction failures
- Deployment confidence: Validated E2E flows increase confidence in releases
- Documentation: Tests serve as executable documentation of system behavior
- Regression prevention: Automated tests catch breaking changes immediately
- Onboarding aid: New developers can understand system by reading integration tests
- Maintainability: Fixture pattern and helpers reduce code duplication
Negative¶
- Test execution time: Integration tests are slower than unit tests (estimated 3-5 minutes for full suite)
- Maintenance overhead: Must update integration tests when contracts change
- Initial investment: Requires upfront time to create fixtures and first tests
- CI/CD complexity: Adds another workflow to maintain in GitHub Actions
Risks and Mitigations¶
Risk: Tests become flaky due to timing issues
- Mitigation: Use time.increase() explicitly instead of relying on block mining
- Mitigation: Avoid race conditions with proper await usage
- Mitigation: Use deterministic test data
Risk: Tests become too slow - Mitigation: Use fixture pattern for efficient state reset - Mitigation: Parallelize independent test files if needed - Mitigation: Monitor test execution time and optimize slow tests
Risk: Tests become outdated as contracts evolve - Mitigation: Include integration tests in code review process - Mitigation: Fail CI/CD if integration tests don't pass - Mitigation: Regular review of test coverage during sprints
Risk: Test maintenance burden - Mitigation: Create helper library to reduce duplication - Mitigation: Document test patterns and conventions - Mitigation: Provide examples and templates for common scenarios
Alternatives Considered¶
Alternative 1: Continue with Unit Tests Only¶
Pros: - No additional work required - Faster test execution - Simpler CI/CD pipeline
Cons: - No validation of E2E workflows - Integration bugs discovered in production - Manual testing required for releases - Poor documentation of system behavior
Why not chosen: Insufficient for validating complex multi-contract interactions critical to system reliability
Alternative 2: Use Foundry for Integration Tests¶
Pros: - Faster test execution (Rust-based) - Built-in fuzzing capabilities - Gas-efficient testing
Cons: - New tooling to learn (Solidity test syntax) - Less mature ecosystem for integration testing - Team unfamiliar with Foundry - Would require maintaining two test frameworks - Harder to simulate complex multi-step workflows
Why not chosen: Team expertise and project investment are in Hardhat ecosystem; adding another framework increases complexity
Alternative 3: End-to-End Tests with Frontend¶
Pros: - Tests entire stack including UI - Validates user experience - Catches frontend integration issues
Cons: - Much slower execution (minutes per test) - More fragile (UI changes break tests) - Harder to debug failures - Doesn't isolate contract issues - Requires maintaining test UI environment
Why not chosen: Too slow and fragile for primary integration testing; better suited for a small smoke test suite
Alternative 4: Manual Testing Checklist¶
Pros: - No code to maintain - Flexible for exploratory testing - Can catch UX issues
Cons: - Time-consuming for each release - Human error prone - Not automated in CI/CD - Poor documentation - Doesn't scale with system complexity
Why not chosen: Not reliable or scalable for continuous integration
Alternative 5: Use hardhat-deploy Plugin¶
Pros: - Advanced deployment management - Tag-based fixture system - Deterministic deployments
Cons: - Additional dependency - Steeper learning curve - Overkill for current needs - Adds complexity to simple scenarios
Why not chosen: Current fixture needs are simple enough for native loadFixture; can add later if needed
Implementation Notes¶
Phase 1: Foundation (Week 1)¶
- Create
test/integration/directory structure - Implement
deploySystemFixtureintest/integration/fixtures/deploySystem.js - Create helper functions library in
test/integration/helpers/index.js - Write first integration test for proposal lifecycle
Phase 2: Core Workflows (Weeks 2-3)¶
- Implement tests for privacy-preserving trading flow
- Implement tests for oracle resolution flow
- Implement tests for ragequit flow
- Implement tests for FairWins market lifecycle
Phase 3: Factory and Edge Cases (Week 4)¶
- Implement tests for DAO factory deployment
- Add error path tests for all workflows
- Add multi-user concurrent operation tests
Phase 4: CI/CD and Documentation (Week 5)¶
- Create
.github/workflows/integration-tests.yml - Add npm scripts for running integration tests
- Update documentation with examples
- Train team on writing integration tests
Success Criteria¶
- All 6 key E2E workflows have passing integration tests
- Integration test suite runs in under 5 minutes
- Zero flaky tests (100% pass rate across 10 runs)
- CI/CD fails on integration test failures
- Integration testing documentation is complete
- At least 2 team members can write integration tests independently
Monitoring¶
Track these metrics monthly: - Integration test count - Test execution time - Pass rate - Coverage of E2E workflows - Bugs caught by integration tests vs. production
References¶
- Hardhat Testing Documentation
- Hardhat Network Helpers
- OpenZeppelin Test Helpers
- Integration Testing Best Practices
- Test Fixtures Pattern
- Internal:
docs/developer-guide/integration-testing.md - Internal:
docs/developer-guide/testing.md
Revision History¶
| Date | Changes | Author |
|---|---|---|
| 2025-12-23 | Initial version | Development Team |