The tests subpackage

All tests can be run with:

$ pytest -v tests/

Tests are organised into four categories using pytest marks. Each category runs as a separate CI job:

$ pytest -v -m unit tests/          # fast, no solver
$ pytest -v -m integration tests/   # solver-dependent
$ pytest -v -m parallel tests/      # multiprocessing
$ pytest -v -m plotting tests/      # matplotlib / plotly

Unit tests (unit)

tests.test_pbl_model module

This module contains unit tests for the src.pbl_model.vertical_profiles() function in the src.pbl_model module. The tests validate the behavior of the function under different closure schemes, including:

  • CONSTANT Closure: Ensures the profiles for velocity and eddy diffusivity are constant and match expected values.

  • MOST (Monin-Obukhov Similarity Theory) Closure: Verifies that the profiles vary with height and are physically reasonable.

The tests use parameterized inputs to check the function’s output shapes, values, and physical consistency across various scenarios.

tests.test_pbl_model.test_both_z0_and_ustar_raises()[source]

Test that providing both z0 and ustar raises ValueError.

tests.test_pbl_model.test_constant_closure(n, meas_height, wind, ustar, prsc)[source]

Test the CONSTANT closure for scalar inputs.

Raises:

AssertionError – If the output shapes do not match the expected dimensions or if the profiles are not constant.

tests.test_pbl_model.test_invalid_closure_raises()[source]

Test that an invalid closure type raises ValueError.

tests.test_pbl_model.test_most_closure(n, meas_height, wind, ustar, mol)[source]

Test the MOST closure for scalar inputs.

Raises:

AssertionError – If the output shapes do not match the expected dimensions or if the profiles are not physically reasonable.

tests.test_pbl_model.test_mostm_closure()[source]

Test the MOSTM (modified MOST) closure has anisotropic diffusion.

tests.test_pbl_model.test_oaahoc_closure()[source]

Test the OAAHOC (one-and-a-half order) closure with explicit TKE.

tests.test_pbl_model.test_oaahoc_closure_default_tke()[source]

Test that OAAHOC defaults TKE to 1.0 when not provided.

tests.test_pbl_model.test_stretch_and_domain_height()[source]

Test custom stretch and domain_height parameters.

tests.test_pbl_model.test_z0_only_path()[source]

Test that providing z0 without ustar derives ustar from z0.

tests.test_config module

Tests for config_parser module.

tests.test_config.test_domain_full_output()[source]

Test that full_output in domain config round-trips correctly.

tests.test_config.test_domain_full_output_default()[source]

Test that full_output defaults to False when not specified.

tests.test_config.test_domain_output_levels()[source]

Test that output_levels in domain config round-trips correctly.

tests.test_config.test_domain_output_levels_default()[source]

Test that output_levels defaults to None when not specified.

tests.test_config.test_latlon_to_xy(lat, lon, ref_lat, ref_lon, exp_x, exp_y, tol)[source]
tests.test_config.test_load_config_file_not_found()[source]
tests.test_config.test_load_config_from_yaml()[source]
tests.test_config.test_met_config_get_step_scalar()[source]
tests.test_config.test_met_config_get_step_timeseries()[source]
tests.test_config.test_met_config_mixed_lengths_raises()[source]
tests.test_config.test_met_config_scalar()[source]
tests.test_config.test_met_config_timeseries()[source]
tests.test_config.test_met_z0()[source]

Test that z0 in met config appears in get_step() result.

tests.test_config.test_met_z0_default()[source]

Test that z0 is not in get_step() when not set.

tests.test_config.test_parse_config_missing_domain()[source]
tests.test_config.test_parse_config_missing_towers()[source]
tests.test_config.test_parse_minimal_config()[source]
tests.test_config.test_solver_analytic()[source]

Test that analytic field in solver config round-trips correctly.

tests.test_config.test_solver_defaults_new_fields()[source]

Test that new solver fields default correctly when not specified.

tests.test_config.test_solver_src_loc()[source]

Test that src_loc in solver config is converted to tuple.

tests.test_config.test_tower_compute_local_xy()[source]

tests.test_synthetic module

Tests for synthetic data generators.

class tests.test_synthetic.TestSyntheticTimeseries[source]

Bases: object

test_compatible_with_met_config()[source]

Output dict should be valid input to MetConfig.

test_reproducibility()[source]
test_timestamps_format()[source]
test_value_ranges()[source]
class tests.test_synthetic.TestTowersGrid[source]

Bases: object

test_compatible_with_tower_config()[source]

Output dicts should be valid input to TowerConfig.

test_invalid_layout_raises()[source]
test_reproducibility()[source]
test_tower_output_structure()[source]

Test tower count, dict keys, and name uniqueness.

tests.test_cache module

Tests for Green’s function caching.

tests.test_cache.cache(tmp_path)[source]
tests.test_cache.solver_inputs()[source]

Minimal inputs matching what the cache hashes.

tests.test_cache.test_cache_clear(cache, solver_inputs)[source]
tests.test_cache.test_cache_different_inputs_miss(cache, solver_inputs)[source]
tests.test_cache.test_cache_integration()[source]

Test caching through the full solver with footprint=True.

tests.test_cache.test_cache_miss(cache, solver_inputs)[source]
tests.test_cache.test_cache_put_and_hit(cache, solver_inputs)[source]

Integration tests (integration)

tests.test_integration module

This module contains an integration test for the interaction between the pbl_model, utils, and solver components.

The test validates the combined behavior of these components by comparing the numerical and analytical solutions for the steady-state advection-diffusion equation. Currently, this test is similar to combining the pbl_model and solver tests, but it is designed to serve as a foundation for future extensions.

Functions:

  • test_integration: Tests the combined behavior of the pbl_model, utils, and solver components.

tests.test_integration.test_convergence_trend()[source]

Verify that numerical error decreases monotonically with resolution.

Runs the solver at 3 resolution levels against the analytic solution (CONSTANT closure) and asserts that relative MSE decreases at each refinement step.

tests.test_integration.test_integration()[source]

Tests the combined behavior of the pbl_model, utils, and solver components.

The test validates:
  • The interaction between the components.

  • The numerical accuracy of the solver by comparing its results to the analytical solution within a specified tolerance.

Raises:

AssertionError – If the numerical and analytical solutions differ beyond the specified tolerance.

tests.test_integration.test_solver_double_precision()[source]

Verify double precision path produces float64 output.

tests.test_integration.test_solver_halo_overflow()[source]

Verify solver handles modes exceeding grid+halo gracefully.

tests.test_integration.test_solver_invalid_precision_raises()[source]

Verify invalid precision raises ValueError.

tests.test_integration.test_solver_non_footprint_shift()[source]

Verify non-footprint mode with non-zero meas_pt (shift path).

tests.test_integration.test_solver_odd_modes_raises()[source]

Verify odd modes raise ValueError.

tests.test_integration.test_solver_single_precision()[source]

Verify single precision path produces float32 output.

tests.test_interface module

Tests for the high-level interface module.

tests.test_interface.test_multitower_structure(multitower_results_session, timeseries_config_session)[source]

Test multitower output: dict keyed by tower names, all timesteps, different footprints.

tests.test_interface.test_single_run_structure(single_run_result, simple_config_session)[source]

Test output structure, shapes, types, and metadata from a single run.

tests.test_interface.test_single_run_with_synthetic_data()[source]

Integration test: synthetic data -> config -> run.

tests.test_interface.test_timeseries_aggregated_footprint(timeseries_results_session)[source]

Test aggregated mean footprint with 50% and 70% flux contribution contours.

tests.test_interface.test_timeseries_footprints_evolve(timeseries_results_session, timeseries_config_session)[source]

Test that changing met conditions produce different footprints at each timestep.

tests.test_interface.test_timeseries_met_params_vary(timeseries_results_session, timeseries_config_session)[source]

Test that time-varying ustar, mol, wind_dir, wind_speed propagate to each result.

tests.test_interface.test_timeseries_structure(timeseries_results_session, timeseries_config_session)[source]

Test timeseries output: list structure, keys, unique timestamps, finite values.

tests.test_io module

Tests for NetCDF I/O.

tests.test_io.test_load_nonexistent_raises()[source]
tests.test_io.test_netcdf_3d_roundtrip()[source]

Test save/load roundtrip with 3D output fields (z dimension).

tests.test_io.test_netcdf_global_attrs(multitower_results_session)[source]

Test that global attributes capture domain and solver config.

tests.test_io.test_netcdf_met_values_match(multitower_results_session)[source]

Test that saved met values match the original result params exactly.

tests.test_io.test_netcdf_metadata(multitower_results_session)[source]

Test CF attributes, met variables, and tower metadata.

tests.test_io.test_netcdf_multitower_select_by_name(multitower_results_session)[source]

Test that individual tower data can be selected by name and matches.

tests.test_io.test_netcdf_roundtrip_and_values(multitower_results_session)[source]

Test save/load roundtrip and verify values match original.

tests.test_io.test_netcdf_single_tower_timeseries(timeseries_results_session, timeseries_config_session)[source]

Test save/load roundtrip for a single tower timeseries.

tests.test_io.test_netcdf_timeseries_timestamps(multitower_results_session)[source]

Test that timestamps are stored correctly and data varies across time.

tests.test_io.test_netcdf_tower_metadata_match(multitower_results_session)[source]

Test that tower lat/lon/z and names match config exactly.

Parallel tests (parallel)

tests.test_parallel module

Tests for parallel execution.

tests.test_parallel.parallel_config()[source]

Config with 2 towers x 2 timesteps for parallel tests.

tests.test_parallel.test_parallel_invalid_strategy(parallel_config)[source]
tests.test_parallel.test_parallel_matches_serial(parallel_config, strategy)[source]
tests.test_parallel.test_parallel_result_structure(parallel_config)[source]
tests.test_parallel.track_pool()[source]

Patch ProcessPoolExecutor to print diagnostics after each test.

Plotting tests (plotting)

tests.test_plotting module

Tests for the plotting module.

tests.test_plotting.test_extract_percentile_contour_3d_input()[source]

extract_percentile_contour auto-slices 3D input.

tests.test_plotting.test_get_source_area_basic()[source]

Test that get_source_area returns correct shape and value range.

tests.test_plotting.test_get_source_area_monotone()[source]

Test that higher g values map to lower rescaled values.

tests.test_plotting.test_maybe_slice_level_2d_passthrough()[source]

2D field and grid pass through unchanged.

tests.test_plotting.test_maybe_slice_level_3d_slicing()[source]

3D field is sliced correctly at the given level.

tests.test_plotting.test_percentile_contour_properties(footprint_result_session)[source]

Test that percentile contours return valid floats with monotonic area.

tests.test_plotting.test_plot_convergence()[source]

Test log-log convergence plot with and without fits.

tests.test_plotting.test_plot_field_comparison()[source]

Test 2x2 field comparison with synthetic data.

tests.test_plotting.test_plot_footprint_comparison(footprint_result_session)[source]

Test multi-panel comparison plot.

tests.test_plotting.test_plot_footprint_field_3d_input()[source]

plot_footprint_field auto-slices 3D input at requested level.

tests.test_plotting.test_plot_footprint_field_variants(footprint_result_session)[source]

Test footprint field plot: basic, with contours, and on custom axes.

tests.test_plotting.test_plot_footprint_interactive(footprint_result_session)[source]
tests.test_plotting.test_plot_footprint_on_map_happy_path(footprint_result_session)[source]

Test map plot with contextily tiles (requires network + contextily).

tests.test_plotting.test_plot_footprint_on_map_import_error(footprint_result_session)[source]

Should raise ImportError with helpful message if contextily missing.

tests.test_plotting.test_plot_footprint_on_map_land_cover_import_error(footprint_result_session)[source]

Should raise ImportError with helpful message if owslib missing.

tests.test_plotting.test_plot_footprint_on_map_land_cover_mock(footprint_result_session, monkeypatch)[source]

Test land cover overlay with mocked WMS response.

tests.test_plotting.test_plot_footprint_timeseries()[source]
tests.test_plotting.test_plot_source_area_contours(footprint_result_session)[source]

Test source area contour plotting returns axes.

tests.test_plotting.test_plot_source_area_contours_custom_ax(footprint_result_session)[source]

Test source area contour plotting on provided axes.

Test gallery plot creates 2x3 grid with 5 visible panels.

tests.test_plotting.test_plot_vertical_profiles()[source]

Test vertical profile plot using real PBL profiles.

tests.test_plotting.test_plot_vertical_slice()[source]

Test 2D slice from a 3D field for all axes.

tests.test_plotting.test_plot_wind_rose_happy_path()[source]

Test wind rose plot with synthetic data (requires windrose).

tests.test_plotting.test_plot_wind_rose_import_error()[source]

Should raise ImportError with helpful message if windrose missing.

tests.test_plotting.test_source_area_base_functions_shapes(footprint_result_session)[source]

Test that all 5 base function constructors return correct shapes.