Testing requirements
- Unit tests: All new functions must have unit tests
- Coverage: Aim for 80%+ coverage. Critical paths should have 90%+ coverage
- Integration tests: Include tests that verify feature interactions
- Benchmark tests: For performance-critical code, include benchmarks
Go testing
Running tests
Using Makefile
The project provides convenient Make targets:Writing unit tests
Follow Go testing conventions:Use table-driven tests to cover multiple scenarios efficiently.
Running a single test
You can run specific tests by name:Benchmark tests
For performance-critical code, include benchmarks:Profiling tests
Profile CPU and memory usage during tests:Rust testing
Running tests
Using Makefile
From the project root:Writing unit tests
Follow Rust testing conventions:Integration tests
Create integration tests insimulator/tests/:
Test coverage
Go coverage
Generate and view coverage reports:Rust coverage
For Rust, you can usetarpaulin or llvm-cov:
Testing best practices
Test naming conventions
Test naming conventions
- Go: Use
Testprefix followed by the function name:TestParseTransaction - Rust: Use descriptive names with underscores:
test_parse_successful_transaction - Benchmarks: Use
Benchmarkprefix in Go:BenchmarkParseTransaction
Test isolation
Test isolation
- Each test should be independent and not rely on other tests
- Use setup and teardown functions to create clean test environments
- Avoid shared mutable state between tests
- Use parallel testing when tests are independent
Test data
Test data
- Use table-driven tests to cover multiple scenarios
- Create helper functions for common test data setup
- Store large test fixtures in separate files
- Use meaningful test data that represents real-world scenarios
Error testing
Error testing
- Test both success and failure cases
- Verify error messages are helpful and accurate
- Test edge cases and boundary conditions
- Ensure error handling doesn’t panic unexpectedly
Mock and stub usage
Mock and stub usage
- Use interfaces to enable mocking in Go
- Create test doubles for external dependencies
- Mock RPC calls and network interactions
- Keep mocks simple and focused
Continuous integration
The CI pipeline runs all tests automatically:- Go tests: Run on Ubuntu with Go 1.23
- Rust tests: Run on stable Rust toolchain
- Coverage checks: Ensure coverage doesn’t decrease
- Race detection: Run tests with
-raceflag
Tests must pass before linting runs. If tests fail, the CI pipeline stops immediately.
Common testing commands
All tests (Go + Rust)
Specific package tests
Watch mode
Test maintenance
- Update tests when changing functionality
- Remove obsolete tests when removing features
- Refactor tests to reduce duplication
- Document complex test scenarios with comments
- Review test failures carefully before ignoring them