Skip to content

Commit 24e9d2b

Browse files
authored
fix: integration test failing on Windows CI(#4)
* use a temp directory under the checkout itself instead, so it's always on the same drive as the Snakefile and conda prefix.
1 parent 97ecd96 commit 24e9d2b

2 files changed

Lines changed: 79 additions & 60 deletions

File tree

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ gurobi.log
3838
# earth-osm cache
3939
data/earth-osm/
4040

41+
# test_snakemake_integration_testing's working directory; normally cleaned
42+
# up automatically, this is only a backstop if that's ever interrupted
43+
.integration-*/
44+
4145
# Personal overrides (e.g. a custom Overpass API endpoint/token), passed via
4246
# --configfile config/config.local.yaml; never committed.
4347
config/config.local.yaml

‎tests/integration_test.py‎

Lines changed: 75 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import shutil
1111
import subprocess
1212
import sys
13+
import tempfile
1314
from pathlib import Path
1415

1516
import pytest
@@ -46,71 +47,85 @@ def test_standard_file_existance(module_path, file):
4647
assert Path(module_path / file).exists()
4748

4849

49-
def test_snakemake_integration_testing(module_path, tmp_path):
50+
def test_snakemake_integration_testing(module_path):
5051
"""Run retrieval from scratch in its Conda environment and validate outputs."""
5152
log_dir = module_path / "tests/integration/logs"
5253
log_dir.mkdir(parents=True, exist_ok=True)
5354
run_log = log_dir / "integration.log"
5455
conda_prefix = module_path / ".snakemake/conda"
55-
try:
56-
with run_log.open("w", encoding="utf-8") as log:
57-
result = subprocess.run(
58-
[
59-
sys.executable,
60-
"-m",
61-
"snakemake",
62-
"--snakefile",
63-
str(module_path / "tests/integration/Snakefile"),
64-
"--directory",
65-
str(tmp_path),
66-
"--use-conda",
67-
"--conda-prefix",
68-
str(conda_prefix),
69-
"--cores",
70-
"1",
71-
"--show-failed-logs",
72-
],
73-
stdout=log,
74-
stderr=subprocess.STDOUT,
75-
timeout=600,
76-
check=False,
77-
env={**os.environ, "XDG_CACHE_HOME": str(tmp_path / "cache")},
56+
57+
# A directory under module_path, not pytest's tmp_path: on Windows CI,
58+
# tmp_path can land on a different drive than the checkout, and
59+
# Snakemake's relative-path handling then fails with "ValueError: path
60+
# is on mount 'D:', start on mount 'C:'". Keeping the working directory
61+
# on the same drive as the Snakefile/conda prefix avoids that. Every
62+
# assertion that reads from workdir has to stay inside this block -
63+
# TemporaryDirectory deletes it on exit.
64+
with tempfile.TemporaryDirectory(
65+
dir=module_path, prefix=".integration-", ignore_cleanup_errors=True
66+
) as temporary_directory:
67+
workdir = Path(temporary_directory)
68+
try:
69+
with run_log.open("w", encoding="utf-8") as log:
70+
result = subprocess.run(
71+
[
72+
sys.executable,
73+
"-m",
74+
"snakemake",
75+
"--snakefile",
76+
str(module_path / "tests/integration/Snakefile"),
77+
"--directory",
78+
str(workdir),
79+
"--use-conda",
80+
"--conda-prefix",
81+
str(conda_prefix),
82+
"--cores",
83+
"1",
84+
"--show-failed-logs",
85+
],
86+
stdout=log,
87+
stderr=subprocess.STDOUT,
88+
timeout=600,
89+
check=False,
90+
env={**os.environ, "XDG_CACHE_HOME": str(workdir / "cache")},
91+
)
92+
finally:
93+
if (workdir / "logs").exists():
94+
shutil.copytree(workdir / "logs", log_dir, dirs_exist_ok=True)
95+
96+
assert result.returncode == 0, run_log.read_text(encoding="utf-8")
97+
output_dir = workdir / "resources/grid-builder/osm/retrieve"
98+
for feature in ("substations_way", "lines_way"):
99+
payload = json.loads(
100+
(output_dir / f"benin_{feature}.json").read_text(encoding="utf-8")
78101
)
79-
finally:
80-
if (tmp_path / "logs").exists():
81-
shutil.copytree(tmp_path / "logs", log_dir, dirs_exist_ok=True)
82-
83-
assert result.returncode == 0, run_log.read_text(encoding="utf-8")
84-
output_dir = tmp_path / "resources/grid-builder/osm/retrieve"
85-
for feature in ("substations_way", "lines_way"):
86-
payload = json.loads(
87-
(output_dir / f"benin_{feature}.json").read_text(encoding="utf-8")
88-
)
89-
elements = payload["elements"]
90-
assert elements, f"No {feature} records retrieved"
91-
assert all(item["geometry"] for item in elements)
92-
93-
build_dir = tmp_path / "resources/grid-builder/osm/build"
94-
for component in ("buses", "lines", "transformers"):
95-
with (build_dir / "csv" / f"{component}.csv").open(encoding="utf-8") as file:
96-
rows = list(csv.DictReader(file))
97-
assert rows or component == "transformers"
98-
99-
with (build_dir / "csv" / "lines.csv").open(encoding="utf-8") as file:
100-
built_lines = list(csv.DictReader(file))
101-
assert all(row["bus0"] != row["bus1"] for row in built_lines)
102-
assert all(float(row["voltage_kv"]) >= 220 for row in built_lines)
103-
104-
for geojson_name in ("stations_polygon", "buses_polygon"):
105-
polygons = json.loads(
106-
(build_dir / "geojson" / f"{geojson_name}.geojson").read_text(
102+
elements = payload["elements"]
103+
assert elements, f"No {feature} records retrieved"
104+
assert all(item["geometry"] for item in elements)
105+
106+
build_dir = workdir / "resources/grid-builder/osm/build"
107+
for component in ("buses", "lines", "transformers"):
108+
with (build_dir / "csv" / f"{component}.csv").open(
107109
encoding="utf-8"
110+
) as file:
111+
rows = list(csv.DictReader(file))
112+
assert rows or component == "transformers"
113+
114+
with (build_dir / "csv" / "lines.csv").open(encoding="utf-8") as file:
115+
built_lines = list(csv.DictReader(file))
116+
assert all(row["bus0"] != row["bus1"] for row in built_lines)
117+
assert all(float(row["voltage_kv"]) >= 220 for row in built_lines)
118+
119+
for geojson_name in ("stations_polygon", "buses_polygon"):
120+
polygons = json.loads(
121+
(build_dir / "geojson" / f"{geojson_name}.geojson").read_text(
122+
encoding="utf-8"
123+
)
108124
)
109-
)
110-
assert polygons["type"] == "FeatureCollection"
111-
112-
country_log = (tmp_path / "logs/grid-builder/retrieve_osm_pbf/benin.log").read_text(
113-
encoding="utf-8"
114-
)
115-
assert "Wrote" in country_log
116-
assert str(conda_prefix) in country_log, "Retrieval must use its Conda Python"
125+
assert polygons["type"] == "FeatureCollection"
126+
127+
country_log = (
128+
workdir / "logs/grid-builder/retrieve_osm_pbf/benin.log"
129+
).read_text(encoding="utf-8")
130+
assert "Wrote" in country_log
131+
assert str(conda_prefix) in country_log, "Retrieval must use its Conda Python"

0 commit comments

Comments
 (0)