This document describes the testing infrastructure for the pietcc compiler and interpreter.
The project uses a multi-layered testing approach:
Unit tests are located alongside the code they test in each crate:
parser/src/- Parser unit testsinterpreter/src/- Interpreter unit testscompiler/cfg_to_ir/src/- Compiler unit testscompiler/optimizer/src/- Optimizer unit testspiet_core/src/- Core library unit tests
Run unit tests:
cargo test --lib --binsIntegration tests are located in tests/integration/:
interpreter_tests.rs- End-to-end interpreter testscompiler_tests.rs- End-to-end compiler tests
These tests compile/interpret actual Piet programs from the images/ directory and verify their output.
Run integration tests:
cargo test --test '*'Test programs are stored in:
images/- Piet program imagestests/fixtures/expected_outputs/- Expected output files
Run all tests:
./scripts/run_tests.sh# Run only unit tests
./scripts/run_tests.sh --unit-only
# Run only integration tests
./scripts/run_tests.sh --integration-only
# Run with verbose output
./scripts/run_tests.sh --verbose
# Skip release build (faster for development)
./scripts/run_tests.sh --no-release# All tests
cargo test
# Specific test
cargo test test_hello_world_interpreter
# With output
cargo test -- --nocapture
# Specific module
cargo test --test interpreter_testsGitHub Actions automatically runs tests on:
- Every push to
mainandtestsbranches - Every pull request to
main
The CI pipeline includes:
- Unit tests
- Integration tests
- Linting (rustfmt + clippy)
- Build verification
- Code coverage
See .github/workflows/ci.yml for details.
- Add test function in the relevant module:
#[test]
fn test_my_function() {
// Test code here
}- Add Piet program image to
images/ - Add expected output to
tests/fixtures/expected_outputs/(optional) - Add test function to
tests/integration/interpreter_tests.rsortests/integration/compiler_tests.rs:
#[test]
fn test_my_program() {
let result = run_interpreter("images/my_program.png", "");
assert!(result.is_ok());
let output = result.unwrap();
assert_eq!(output, "expected output");
}The images/ directory contains a variety of test programs:
hw.png- Hello Worldhi.png- Simple greetingpower2.png- Powers of 2piet_factorial.png- Factorial calculationadder.png- Additioneuclid_clint.png- GCD algorithmpiet_pi.png- Pi calculationfizzbuzz.png- FizzBuzz99bottles.png- 99 Bottles of Beererat2.png- Sieve of Eratosthenespietquest.png- Large adventure game
To generate coverage report:
cargo install cargo-tarpaulin
cargo tarpaulin --all-features --workspace --timeout 300# Run interpreter manually
./target/release/pietcc --interpret images/hw.png
# With debug output
RUST_BACKTRACE=1 ./target/release/pietcc --interpret images/hw.png# Compile program manually
./target/release/pietcc --compile images/hw.png -o test_output
# Run compiled program
./test_output
# View LLVM IR
./target/release/pietcc --compile images/hw.png -o test_output.ll
cat test_output.llMake sure LLVM 18 is installed:
# Ubuntu
sudo apt-get install llvm-18-dev libpolly-18-dev
# macOS
brew install llvm@18
export LLVM_SYS_180_PREFIX=$(brew --prefix llvm@18)Some complex programs may take longer to compile/run. Increase timeout:
cargo test -- --test-threads=1 --nocaptureTests expect to run from the project root directory. Make sure you're in /path/to/pietcc/ when running tests.
When contributing code:
- Write unit tests for new functions
- Add integration tests for new features
- Ensure all tests pass:
./scripts/run_tests.sh - Run linter:
cargo clippy - Format code:
cargo fmt
The CI will automatically verify all of these on pull requests.