Skip to content

Testing

Sunil Anandatheertha edited this page May 22, 2026 · 1 revision

Testing and Coverage

UPXO has a pytest suite under tests/ in the repository root, run automatically on every push to dev and on pull requests to main. Coverage is intentionally focused on stable utility functions at this stage and will expand over time.


CI Environment

Item Detail
Runner ubuntu-latest (GitHub-hosted)
OS Ubuntu Linux
Python 3.13
Trigger Push to dev; pull requests to main
Excluded pyvista / VTK (requires OpenGL — not available on the Ubuntu runner)
Test command pytest tests/ -v

OS note: UPXO is developed and verified locally on Windows 11. The CI runner uses Ubuntu Linux. All 22 tests that execute in CI produce identical results on both platforms. One test (_merge_small_grains) is skipped in CI due to the VTK/OpenGL constraint described below, but passes on Windows.

Workflow definition: .github/workflows/test.yml


What Is Tested

Smoke

Function / check What it verifies
import upxo; upxo.__version__ Package imports without error; version string is non-empty

Data utilities (_sup/data_ops.py)

Function What the test checks
distance_between_two_points (0,0)→(3,4) returns 5.0 (3-4-5 triangle)
calculate_angular_distance Orthogonal vectors → π/2; parallel vectors → 0
find_outliers_iqr [1,2,3,4,100] in mode 'both' — index 4 (value 100) detected

Type handlers (_sup/dataTypeHandlers.py)

Function What the test checks
are_all_numbers [1,2,3.0]True; [1,'a']False
strip_str Underscore removed from 'pol_area'
DEEPCHECK_is_coord2d_list [[1,2],[3,4]]True; [[1,2,3],[4,5,6]]False

Grid operations (gsdataops/grid_ops.py)

Function What the test checks
section_from_3d 4×4×4 array: axis=0 loc=0 returns correct 4×4 slice; axis=1 loc=2 likewise
resample_grid_2d 10×10 array with uigrid=None, sf=0.5 → output smaller than input
rescale_grid_2d 5×5 array, scale_factor=2.0 → 10×10 output

Grain ID operations (gsdataops/gid_ops.py)

Function What the test checks
find_small_fids Single-pixel grain ID is returned; large grains are excluded
find_boundary_fids2d Grains touching all four edges are present in result
find_O1_neigh_2d Returns a dict keyed by every grain ID; result is symmetric (if A neighbours B, B neighbours A)

Sampling (statops/sampling.py)

Function What the test checks
in_limits Point inside bounds → True; point outside → False
bridson_uniform_density All returned points lie within [0, width) × [0, height)

Smoothing (pxtalops/gssmooth2d.py)

Function What the test checks CI status
_merge_small_grains LFI with 1-pixel grain: unique grain count decreases after merge Skipped (VTK not available — see below)

Coverage by Module

Module Source file Tested Total public functions Coverage
data_ops _sup/data_ops.py 3 20 15%
dataTypeHandlers _sup/dataTypeHandlers.py 3 38 8%
grid_ops gsdataops/grid_ops.py 3 48 6%
gid_ops gsdataops/gid_ops.py 3 34 9%
sampling statops/sampling.py 2 13 15%
gssmooth2d pxtalops/gssmooth2d.py 1 13 8%
Total 15 166 ~9%

Smoke test and fixtures excluded from the count.


Known Limitations

Skipped in CI — _merge_small_grains

gssmooth2d transitively imports VTK through this chain:

gssmooth2d → geometrification → mulsline2d / mulpoint2d → vtk

VTK requires OpenGL system libraries not present on the GitHub Actions Ubuntu runner. The test is guarded with pytest.importorskip("vtk") — it is skipped cleanly on CI and passes on Windows where pyvista (which bundles VTK) is installed.

No integration-level tests

The full MCGS pipeline — mcgs()simulate()detect_grains()char_morph_2d() — requires an Excel dashboard file and significant compute time. It is not tested in CI. This is the most user-facing workflow and is validated through the demo notebooks (gschar1.ipynb, gschar2.ipynb).

No 3D operation tests

gid_ops and grid_ops both contain 3D variants of every tested 2D function (find_boundary_fids3d, rescale_grid_3d, detect_grains_3d, etc.). None are currently covered.

No visualisation or meshing tests

upxo.viz, upxo.meshing, and upxo.interfaces (Abaqus, DAMASK, MOOSE, Dream.3D) are entirely untested. These modules depend on pyvista, VTK, and external FE tools that cannot run in a standard CI environment.

Limited parameter variation

Most tested functions are covered with a single representative input. The following edge cases are not yet exercised:

  • find_outliers_iqr: modes 'above', 'below', 'in-between'
  • resample_grid_2d: non-default sf values and provided uigrid objects
  • find_O1_neigh_2d: include_central_grain=True, p < 1.0
  • _merge_small_grains: area_threshold > 1; multiple small grains simultaneously
  • section_from_3d: axis=2

Roadmap

The following additions are planned, roughly in priority order:

  • Integration smoke test — verify mcgs() constructs and simulate() runs on a minimal parameter set without requiring an Excel file
  • 3D operation coveragefind_boundary_fids3d, rescale_grid_3d, section_from_3d axis=2
  • Broader parameter coverage — remaining modes of find_outliers_iqr; include_central_grain=True in find_O1_neigh_2d
  • Smoothing variants_merge_small_grains with multiple thresholds
  • Windows CI runner — add a second CI job targeting windows-latest to verify cross-platform consistency

Contributing Tests

Tests live in tests/ and mirror the source package structure (tests/gsdataops/ covers gsdataops/, etc.). Shared fixtures are in tests/conftest.py. Any pull request that adds tests for currently uncovered functions is welcome — follow the existing fixture and assertion patterns.

Clone this wiki locally