Testing
Guide to running and writing tests for Tarang.jl.
Running Tests
Full Test Suite
julia --project=. -e 'using Pkg; Pkg.test()'Specific Test File
julia --project=. test/test_specific.jlWith MPI
The multi-rank MPI tests each run in their own mpiexec world, via a driver (CI exercises 1, 2, and 4 ranks):
julia --project=. test/run_mpi_ci.jl 4 # all MPI tests at 4 ranks
./test/run_mpi_tests.sh 4 # convenience wrapperGPU
GPU tests need an NVIDIA GPU and run on JuliaGPU Buildkite CI (see Continuous Integration). To run them locally on a CUDA host:
julia --project=. -e 'using Pkg; Pkg.add("CUDA")' # CUDA is a weak dependency
julia --project=. test/run_gpu_ci.jl # single-process GPU tests
# distributed (NCCL) tests across, e.g., 2 GPUs:
TARANG_MPI_FILESET=distributed_gpu julia --project=. test/run_mpi_ci.jl 2Test Structure
test/
├── runtests.jl # Main test runner
├── test_cfl.jl # CFL condition tests
├── test_domain_metadata.jl # Domain tests
├── test_solvers.jl # Solver tests
├── test_flow_tools.jl # Analysis tools
├── test_quick_domains.jl # Domain helpers
├── test_plot_tools.jl # Visualization
└── test_compatibility.jl # Compatibility testsWriting Tests
Basic Test
using Test
using Tarang
@testset "My Feature" begin
# Setup
coords = CartesianCoordinates("x")
dist = Distributor(coords; mesh=(1,), dtype=Float64)
# Test
@test dist.size == 1
@test dist.rank == 0
endTesting Fields
@testset "ScalarField" begin
coords = CartesianCoordinates("x")
dist = Distributor(coords; mesh=(1,), dtype=Float64)
basis = RealFourier(coords["x"]; size=8, bounds=(0.0, 2π))
field = ScalarField(dist, "T", (basis,), Float64)
# Test creation
@test field.name == "T"
@test field.dtype == Float64
# Test data
Tarang.ensure_layout!(field, :g)
get_grid_data(field) .= 1.0
@test all(get_grid_data(field) .== 1.0)
endTesting Transforms
@testset "Transforms" begin
# Setup
field = ScalarField(dist, "f", (basis,), Float64)
# Initialize in grid space
Tarang.ensure_layout!(field, :g)
get_grid_data(field) .= sin.(x_grid)
# Transform to spectral
Tarang.ensure_layout!(field, :c)
# Transform back
Tarang.ensure_layout!(field, :g)
# Check roundtrip
@test get_grid_data(field) ≈ sin.(x_grid) atol=1e-10
endTesting Solvers
@testset "IVP Solver" begin
# Setup problem
problem = IVP([field])
Tarang.add_equation!(problem, "∂t(f) = -f")
# Create solver
solver = InitialValueSolver(problem, RK222(); dt=0.01)
# Run
step!(solver)
# Check
@test solver.sim_time ≈ 0.01
@test solver.iteration == 1
endTest Patterns
Analytical Comparison
@testset "Analytical Solution" begin
# Solve diffusion equation
# Compare with exact solution
exact = exp.(-kappa * k^2 * t) .* initial
@test maximum(abs.(numerical .- exact)) < 1e-6
endConvergence Test
@testset "Convergence" begin
errors = Float64[]
for N in [16, 32, 64, 128]
# Solve at resolution N
error = compute_error(N)
push!(errors, error)
end
# Check spectral convergence
for i in 2:length(errors)
@test errors[i] < errors[i-1] / 2
end
endMPI Test
@testset "MPI Parallelism" begin
MPI.Init()
rank = MPI.Comm_rank(MPI.COMM_WORLD)
size = MPI.Comm_size(MPI.COMM_WORLD)
# Test distributed computation
local_sum = compute_local()
global_sum = MPI.Allreduce(local_sum, MPI.SUM, MPI.COMM_WORLD)
@test global_sum ≈ expected_total
MPI.Finalize()
endTest Coverage
Generate Coverage Report
using Coverage
# Run tests with coverage
coverage = process_folder()
# Print summary
println(coverage)Continuous Integration
CPU tests run on GitHub Actions for every push and pull request:
- the default suite on Julia 1.10/1.11/1.12 across Linux, macOS, and Windows;
- the optional CPU feature tests (
TARANG_ONLY_OPTIONAL_TESTS=true); - the MPI suite via
test/run_mpi_ci.jlat 1, 2, and 4 ranks.
GPU tests cannot run on GitHub-hosted runners (no NVIDIA GPU), so they run on the JuliaGPU Buildkite CI, defined in .buildkite/pipeline.yml:
- a single-GPU job (
test/run_gpu_ci.jl) on Julia 1.10/1.11/1.12; - a multi-GPU NCCL job (
test/run_mpi_ci.jlwith thedistributed_gpufileset, 2 ranks).
Because CUDA is a weak dependency and NCCL is loaded dynamically — which keeps CPU installs lean — these jobs Pkg.add CUDA/NCCL before running instead of using the standard package test target.
The Buildkite pipeline is inert until the repository is added to the JuliaGPU Buildkite organization (free for open-source packages): ask on the Julia Slack #gpu channel for a Buildkite admin to create the pipeline, with the Buildkite GitHub App installed on the hosting account. The pipeline file is then run automatically on each push/PR.
See Also
- Contributing: Development guidelines
- Architecture: Code structure