Testing in AGNI
This document describes the testing infrastructure and how to run tests for AGNI.
Running Tests
Prerequisites
Before running tests, ensure that the RAD_DIR environment variable is set to your SOCRATES installation:
export RAD_DIR=/path/to/SOCRATESRun All Tests
From the AGNI root directory:
julia --project=. test/runtests.jlRun Fast Tests Only
The fast test suite excludes expensive integration tests:
julia --project=. test/runtests.jl fastTest Coverage
Generating Coverage Reports
Run Tests with Coverage
From the AGNI root directory:
julia --project=. --code-coverage test/runtests.jlProcess Coverage Data
From the AGNI root directory:
julia --project=. test/get_coverage.jlThis generates:
coverage.info- LCOV format coverage datacoverage.json- Codecov JSON formatcoverage.total- Single number with overall coverage percentagecoverage.md- Markdown formatted file with report on coverage
The coverage.md file outlines:
- Overall coverage percentage
- Per-file coverage breakdown with color coding (🔴 <50%, 🟡 50-80%, 🟢 >80%)
- Files needing attention (<50% coverage)
- Quick wins (small files with 0% coverage)
- Lists of uncovered line numbers
Test Design Principles
- Fast by default: Most tests avoid expensive operations like full atmosphere allocation
- Unit-focused: Each test targets specific functions or small groups of related functions
- Self-contained: Tests don't depend on external files when possible (except SOCRATES spectral files)
- Comprehensive: Tests cover:
- Normal operation (happy path)
- Edge cases (boundary conditions, empty inputs)
- Error conditions (missing files, invalid inputs)
- Type stability and return value validation
Example Test Pattern
using Test
using AGNI
@testset "module_name" begin
@testset "function_name" begin
# Test normal case
result = AGNI.module.function(valid_input)
@test result > 0
@test typeof(result) == Float64
# Test edge case
result_edge = AGNI.module.function(edge_case_input)
@test isfinite(result_edge)
# Test error handling
@test_throws ErrorException AGNI.module.function(invalid_input)
end
endAdding New Tests
When adding new tests:
- Create a new test file in
test/following the naming conventiontest_<module>.jl - Any
test_*.jlfile intest/will be picked up automatically bytest/runtests.jl, so no manual edit totest/runtests.jlis needed - Follow the existing test patterns (see above)
- Avoid expensive operations:
- Don't call
allocate!,setup!, ordeallocate!unless absolutely necessary - Use minimal atmosphere configurations when needed
- Keep test execution time under 5 seconds per file
- Don't call
- Clean up temporary files created during tests
- Test both success and failure paths
- Use descriptive test names in
@testsetblocks
Coverage Goals
- Target: >80% line coverage for utility modules (
phys,consts,ocean,guillot,blake) - Acceptable: >50% for core simulation modules (
atmosphere,energy,solver) - Document: Any intentionally untested code (e.g., platform-specific branches)
Troubleshooting the tests
Tests fail with "RAD_DIR not set"
Ensure RAD_DIR points to a valid SOCRATES installation:
export RAD_DIR=/path/to/SOCRATESTests fail with "Spectral file not found"
The test suite expects spectral files in res/spectral_files/. Ensure AGNI's resource directory is complete.
Coverage is 0% or unexpectedly low
- Make sure you ran tests with
--code-coverageflag - Run
get_coverage.jlfrom the AGNI root directory (nottest/) - Check that
.covfiles were generated insrc/andtest/
Test Maintenance
- Run tests before committing changes
- Update tests when modifying function signatures or behavior
- Keep test execution time reasonable (fast suite <30 seconds)
- Regularly review coverage reports to identify untested code paths