Skip to main content
Testing is a critical part of maintaining code quality in the Erst project. All contributions must include appropriate tests.

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
All tests must pass locally before submitting a pull request. PRs with failing tests will not be merged.

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:
Run benchmarks with:

Profiling tests

Profile CPU and memory usage during tests:
With Make:

Rust testing

Running tests

Using Makefile

From the project root:

Writing unit tests

Follow Rust testing conventions:

Integration tests

Create integration tests in simulator/tests/:

Test coverage

Go coverage

Generate and view coverage reports:

Rust coverage

For Rust, you can use tarpaulin or llvm-cov:

Testing best practices

  • Go: Use Test prefix followed by the function name: TestParseTransaction
  • Rust: Use descriptive names with underscores: test_parse_successful_transaction
  • Benchmarks: Use Benchmark prefix in Go: BenchmarkParseTransaction
  • 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
  • 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
  • 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
  • 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:
  1. Go tests: Run on Ubuntu with Go 1.23
  2. Rust tests: Run on stable Rust toolchain
  3. Coverage checks: Ensure coverage doesn’t decrease
  4. Race detection: Run tests with -race flag
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
Never commit code that makes existing tests fail. Either fix the code or update the tests to reflect the new behavior.