|
4 | 4 |
|
5 | 5 | import pandas as pd |
6 | 6 | import pytest |
| 7 | +import shutil |
7 | 8 |
|
8 | 9 | from data_pipeline.shared.run_context import RunContext |
9 | 10 | from data_pipeline.stages.publish_lifecycle import ( |
10 | 11 | init_report, |
11 | 12 | log_info, |
12 | 13 | log_error, |
13 | 14 | run_integrity_gate, |
| 15 | + promote_semantic_version, |
14 | 16 | ) |
15 | 17 |
|
16 | 18 |
|
@@ -119,9 +121,9 @@ def test_run_integrity_gate_success( |
119 | 121 | assert "Pre-publishing validation passed" in report["info"] |
120 | 122 |
|
121 | 123 |
|
122 | | -def test_run_integrity_gate_fails_on_missing_directory(): |
| 124 | +def test_run_integrity_gate_fails_on_missing_directory(tmp_path): |
123 | 125 |
|
124 | | - run_context = RunContext.create() |
| 126 | + run_context = RunContext.create(base_path=tmp_path) |
125 | 127 |
|
126 | 128 | report = run_integrity_gate(run_context) |
127 | 129 |
|
@@ -227,6 +229,110 @@ def test_run_integrity_gate_fails_on_missing_columns( |
227 | 229 | ) |
228 | 230 |
|
229 | 231 |
|
| 232 | +# ------------------------------------------------------------ |
| 233 | +# PRE-PUBLISH VALIDATION GATE |
| 234 | +# ------------------------------------------------------------ |
| 235 | + |
| 236 | + |
| 237 | +def test_promote_semantic_version_success( |
| 238 | + tmp_path, |
| 239 | + valid_seller_fact, |
| 240 | + valid_seller_dim, |
| 241 | +): |
| 242 | + |
| 243 | + run_context = RunContext.create(base_path=tmp_path, run_id="20230101T000000_abc123") |
| 244 | + run_context.initialize_directories() |
| 245 | + |
| 246 | + valid_seller_fact.to_parquet( |
| 247 | + run_context.semantic_path / "seller_week_performance_fact_2023_01.parquet", |
| 248 | + index=False, |
| 249 | + ) |
| 250 | + |
| 251 | + valid_seller_dim.to_parquet( |
| 252 | + run_context.semantic_path / "seller_dim_2023_01.parquet", |
| 253 | + index=False, |
| 254 | + ) |
| 255 | + |
| 256 | + report = promote_semantic_version(run_context) |
| 257 | + |
| 258 | + assert "success" in report["status"] |
| 259 | + assert "Semantic artifacts promoted successfully" in report["info"] |
| 260 | + |
| 261 | + |
| 262 | +def test_promote_semantic_version_fails_on_existing_version_directory( |
| 263 | + tmp_path, |
| 264 | + valid_seller_fact, |
| 265 | + valid_seller_dim, |
| 266 | +): |
| 267 | + |
| 268 | + run_context = RunContext.create(base_path=tmp_path, run_id="20230101T000000_abc123") |
| 269 | + run_context.initialize_directories() |
| 270 | + |
| 271 | + valid_seller_fact.to_parquet( |
| 272 | + run_context.semantic_path / "seller_week_performance_fact_2023_01.parquet", |
| 273 | + index=False, |
| 274 | + ) |
| 275 | + |
| 276 | + valid_seller_dim.to_parquet( |
| 277 | + run_context.semantic_path / "seller_dim_2023_01.parquet", |
| 278 | + index=False, |
| 279 | + ) |
| 280 | + |
| 281 | + # Initial run that created the directory |
| 282 | + _ = promote_semantic_version(run_context) |
| 283 | + |
| 284 | + # Fails due to existing version directory on same run_id |
| 285 | + report = promote_semantic_version(run_context) |
| 286 | + |
| 287 | + assert "failed" in report["status"] |
| 288 | + assert "Version directory already exists" in report["errors"] |
| 289 | + |
| 290 | + |
| 291 | +def test_promote_semantic_version_fails_on_making_directory(tmp_path): |
| 292 | + |
| 293 | + run_context = RunContext.create(base_path=tmp_path, run_id="20230101T000000_abc123") |
| 294 | + run_context.initialize_directories() |
| 295 | + |
| 296 | + # Force mkdir to raise |
| 297 | + run_context.version_path.mkdir(parents=True) |
| 298 | + |
| 299 | + report = promote_semantic_version(run_context) |
| 300 | + |
| 301 | + assert report["status"] == "failed" |
| 302 | + assert any("File exists" in e or "exists" in e for e in report["errors"]) |
| 303 | + |
| 304 | + |
| 305 | +def test_promote_semantic_version_fails_on_copying_semantic( |
| 306 | + tmp_path, |
| 307 | + monkeypatch, |
| 308 | + valid_seller_fact, |
| 309 | + valid_seller_dim, |
| 310 | +): |
| 311 | + |
| 312 | + run_context = RunContext.create(base_path=tmp_path, run_id="20230101T000000_abc123") |
| 313 | + run_context.initialize_directories() |
| 314 | + |
| 315 | + valid_seller_fact.to_parquet( |
| 316 | + run_context.semantic_path / "seller_week_performance_fact_2023_01.parquet", |
| 317 | + index=False, |
| 318 | + ) |
| 319 | + valid_seller_dim.to_parquet( |
| 320 | + run_context.semantic_path / "seller_dim_2023_01.parquet", |
| 321 | + index=False, |
| 322 | + ) |
| 323 | + |
| 324 | + # force shutil.copy2 to raise |
| 325 | + def mock_copy2(*args, **kwargs): |
| 326 | + raise RuntimeError("copy failure") |
| 327 | + |
| 328 | + monkeypatch.setattr(shutil, "copy2", mock_copy2) |
| 329 | + |
| 330 | + report = promote_semantic_version(run_context) |
| 331 | + |
| 332 | + assert report["status"] == "failed" |
| 333 | + assert any("copy failure" in e for e in report["errors"]) |
| 334 | + |
| 335 | + |
230 | 336 | # ============================================================================= |
231 | 337 | # UNIT TESTS END |
232 | 338 | # ============================================================================= |
0 commit comments