Test Framework Overview
Leo includes a comprehensive test framework located incrates/test-framework/ that supports:
- Unit tests within test programs
- Integration tests in the
tests/directory - Expectation-based testing with automatic output comparison
- Parallel test execution
Writing Unit Tests
Test Program Structure
Tests are written in separate.leo files in the tests/ directory:
Basic Test Example
Create a test program that imports your main program:tests/test_my_project.leo
Test programs must import the program they’re testing and use the
@test annotation on test functions.Test Annotations
Leo provides several test annotations:@test
@test
Marks a function as a test case:
@should_fail
@should_fail
Indicates the test should fail or panic:
Script Tests
You can also write standalone test scripts:Assertions
assert_eq
Compare two values for equality:assert_neq
Compare two values for inequality:Complex Assertions
Test with complex data structures:Running Tests
Run All Tests
Execute all tests in your project:Run Specific Tests
Use theTEST_FILTER environment variable to run specific tests:
Update Expectations
When test output changes intentionally, update expectation files:Test Framework Internals
The Leo test framework (fromcrates/test-framework/src/lib.rs):
1
Test Discovery
Scans the
tests/{category} directory for .leo files:2
Test Execution
Runs each test through the runner function:
3
Output Comparison
Compares output against expectation files in
expectations/{category}/:Parallel Execution
Tests run in parallel by default using Rayon:Integration Testing
Testing with Dependencies
Test programs can have their own dependencies:program.json
Testing with Multiple Programs
Test interactions between programs:tests/test_interaction.leo
Testing Async and Finalize
Testing Mappings
Test programs that use on-chain storage:tests/test_registry.leo
Testing Records
Test private record creation and manipulation:Compiler Test Categories
The Leo compiler includes extensive tests organized by category:Running Compiler Tests
Best Practices
1
Test One Thing
Each test should verify a single behavior:
2
Use Descriptive Names
Test names should describe what they verify:
3
Test Edge Cases
Include tests for boundary conditions:
4
Test Failure Cases
Verify error conditions with
@should_fail:CI/CD Integration
Leo tests integrate with continuous integration:CircleCI Example
GitHub Actions Example
Next Steps
- Learn debugging techniques for failing tests
- Review best practices for test coverage
- Explore package management for test dependencies