Skip to content

Commit 385b379

Browse files
Replace git LFS test data with earthaccess integration tests
Add earthaccess-based fixtures to download ICESat-2 ATL06 granules for integration testing. Granules are cached locally to avoid repeated downloads. Update CI workflow to support integration tests with NASA Earthdata credentials.
1 parent 34b34c3 commit 385b379

5 files changed

Lines changed: 116 additions & 6 deletions

File tree

.github/workflows/reusable_run_tests.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ on:
1010
secrets:
1111
codecov_token:
1212
required: true
13+
EARTHDATA_USERNAME:
14+
description: 'NASA Earthdata username'
15+
required: false
16+
EARTHDATA_PASSWORD:
17+
description: 'NASA Earthdata password'
18+
required: false
1319
workflow_dispatch:
1420

1521
env:
@@ -45,9 +51,13 @@ jobs:
4551
run: |
4652
poetry run ruff check ncompare
4753
48-
- name: Run tests with coverage
54+
- name: Run unit tests with coverage
4955
run: |
50-
poetry run pytest --cov=ncompare --cov-report=xml:build/reports/coverage${{ matrix.python-version }}.xml
56+
poetry run pytest -v -m "not integration" --cov=ncompare --cov-report=xml:build/reports/coverage${{ matrix.python-version }}.xml
57+
58+
- name: Run integration tests with coverage
59+
run: |
60+
poetry run pytest -v -m integration --cov=ncompare --cov-report=xml:build/reports/coverage${{ matrix.python-version }}.xml
5161
5262
- name: Upload coverage reports to Codecov
5363
uses: codecov/codecov-action@v5

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ colorama = ">=0.4.6"
3131
openpyxl = ">=3.1.2"
3232
h5py = ">=3.12.1"
3333
h5netcdf = ">=1.4.1"
34+
earthaccess = ">=0.15.1"
3435

3536
[tool.poetry.group.dev.dependencies]
3637
pytest = ">=7.4.2,<9.0.0"
@@ -48,6 +49,15 @@ mkdocs-material = ">=9.5.12"
4849
requires = ["poetry-core>=1.0.0"]
4950
build-backend = "poetry.core.masonry.api"
5051

52+
[tool.pytest.ini_options]
53+
markers = [
54+
"integration: marks tests as integration tests (downloads data, requires auth)",
55+
"slow: marks tests as slow running",
56+
]
57+
# Skip integration tests by default
58+
addopts = "-v -m 'not integration'"
59+
testpaths = ["tests"]
60+
5161
[[tool.mypy.overrides]]
5262
module = [
5363
"colorama.*",

tests/conftest.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2424
# See the License for the specific language governing permissions and limitations under the License.
2525

26+
import os
2627
from pathlib import Path
2728

29+
import earthaccess
2830
import netCDF4 as nC
2931
import numpy as np
3032
import pytest
@@ -33,6 +35,89 @@
3335
from ncompare.printing import Outputter
3436

3537

38+
@pytest.fixture(scope="session")
39+
def icesat2_cache_dir():
40+
"""Persistent cache directory for ICESat-2 test data."""
41+
cache_dir = Path.home() / ".cache" / "icesat2_test_data"
42+
cache_dir.mkdir(parents=True, exist_ok=True)
43+
return cache_dir
44+
45+
46+
@pytest.fixture(scope="session")
47+
def earthdata_auth():
48+
"""
49+
Authenticate with NASA Earthdata.
50+
Uses credentials from environment variables or .netrc file.
51+
"""
52+
# Check for environment variables (used in CI)
53+
username = os.getenv("EARTHDATA_USERNAME")
54+
password = os.getenv("EARTHDATA_PASSWORD")
55+
56+
if username and password:
57+
earthaccess.login(strategy="environment")
58+
else:
59+
# Use .netrc or prompt for local testing
60+
earthaccess.login()
61+
62+
return True
63+
64+
65+
@pytest.fixture(scope="session")
66+
def icesat2_atl06_granule_1(icesat2_cache_dir, earthdata_auth):
67+
"""
68+
Download or use cached ICESat-2 ATL06 granule #1 for comparison tests.
69+
Temporal range: 2023-08-16 16:16:15 to 2023-08-16 16:25:00
70+
"""
71+
# Check if already cached
72+
cached_files = list(icesat2_cache_dir.glob("ATL06_20230816161508_*.h5"))
73+
if cached_files:
74+
return str(cached_files[0])
75+
76+
# Download if not cached
77+
results = earthaccess.search_data(
78+
short_name="ATL06", temporal=("2023-08-16 16:16:15", "2023-08-16 16:25:00"), count=1
79+
)
80+
81+
if not results:
82+
pytest.skip("ICESat-2 granule #1 not found for test")
83+
84+
# Download the data
85+
files = earthaccess.download(results, str(icesat2_cache_dir))
86+
87+
if not files:
88+
pytest.skip("Failed to download ICESat-2 granule #1")
89+
90+
return files[0]
91+
92+
93+
@pytest.fixture(scope="session")
94+
def icesat2_atl06_granule_2(icesat2_cache_dir, earthdata_auth):
95+
"""
96+
Download or use cached ICESat-2 ATL06 granule #2 for comparison tests.
97+
Temporal range: 2023-08-16 23:46:00 to 2023-08-16 23:48:00
98+
"""
99+
# Check if already cached
100+
cached_files = list(icesat2_cache_dir.glob("ATL06_20230816234629_*.h5"))
101+
if cached_files:
102+
return str(cached_files[0])
103+
104+
# Download if not cached
105+
results = earthaccess.search_data(
106+
short_name="ATL06", temporal=("2023-08-16 23:46:00", "2023-08-16 23:48:00"), count=1
107+
)
108+
109+
if not results:
110+
pytest.skip("ICESat-2 granule #2 not found for test")
111+
112+
# Download the data
113+
files = earthaccess.download(results, str(icesat2_cache_dir))
114+
115+
if not files:
116+
pytest.skip("Failed to download ICESat-2 granule #2")
117+
118+
return files[0]
119+
120+
36121
@pytest.fixture(scope="session")
37122
def temp_data_dir(tmpdir_factory) -> Path:
38123
return Path(tmpdir_factory.mktemp("data"))

tests/test_core.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,23 @@ def test_zero_for_comparison_with_no_differences(ds_3dims_3vars_4coords_1subgrou
7474
assert compare(ds_3dims_3vars_4coords_1subgroup, ds_3dims_3vars_4coords_1subgroup) == 0
7575

7676

77-
def test_icesat(temp_data_dir):
77+
@pytest.mark.integration
78+
def test_icesat(temp_data_dir, icesat2_atl06_granule_1, icesat2_atl06_granule_2):
7879
# Compare the `ncompare` output when testing ICESat
7980
out_path = temp_data_dir / "output_file_icesat-2-atl06.txt"
8081

8182
num_differences = compare(
82-
data_for_tests_dir / "icesat-2-ATL06" / "ATL06_20230816161508_08782002_006_02.h5",
83-
data_for_tests_dir / "icesat-2-ATL06" / "ATL06_20230816234629_08822013_006_01.h5",
83+
icesat2_atl06_granule_1,
84+
icesat2_atl06_granule_2,
8485
show_chunks=True,
8586
show_attributes=True,
8687
file_text=str(out_path),
8788
)
8889

90+
# Verify that differences were found and output was written
91+
assert num_differences > 0, "Expected to find differences between granules"
92+
assert out_path.exists(), "Output file was not created"
93+
8994
assert num_differences == 5280
9095

9196

0 commit comments

Comments
 (0)