|
1 | 1 | from datetime import UTC, datetime |
2 | | -from unittest.mock import patch |
| 2 | +from unittest.mock import MagicMock, patch |
3 | 3 | from uuid import uuid4 |
4 | 4 |
|
5 | 5 | import pytest |
@@ -495,3 +495,85 @@ def test_aggregate_cat_tests_handles_null_max_query_chars(): |
495 | 495 | assert grouped_defs == [[td]] |
496 | 496 |
|
497 | 497 |
|
| 498 | +# --- TestExecutionSQL._get_params baseline guards --- |
| 499 | + |
| 500 | + |
| 501 | +def _make_params_execution_sql() -> TestExecutionSQL: |
| 502 | + """Build a minimal TestExecutionSQL for exercising _get_params without a database.""" |
| 503 | + instance = TestExecutionSQL.__new__(TestExecutionSQL) |
| 504 | + flavor_service = MagicMock() |
| 505 | + flavor_service.quote_character = '"' |
| 506 | + flavor_service.varchar_type = "VARCHAR" |
| 507 | + instance.flavor_service = flavor_service |
| 508 | + instance.flavor = "postgresql" |
| 509 | + instance.table_group = MagicMock(id=uuid4()) |
| 510 | + instance.test_run = MagicMock(test_suite_id=uuid4(), id=uuid4()) |
| 511 | + instance.run_date = datetime(2026, 1, 1, tzinfo=UTC) |
| 512 | + return instance |
| 513 | + |
| 514 | + |
| 515 | +def test_get_params_empty_baseline_counts_become_null(): |
| 516 | + """Empty baseline counts must render as NULL, not "", to avoid CAST( AS FLOAT) syntax errors.""" |
| 517 | + instance = _make_params_execution_sql() |
| 518 | + params = instance._get_params(_make_td(test_type="Missing_Pct", baseline_ct="", baseline_value_ct="")) |
| 519 | + assert params["BASELINE_CT"] == "NULL" |
| 520 | + assert params["BASELINE_VALUE_CT"] == "NULL" |
| 521 | + |
| 522 | + |
| 523 | +def test_get_params_none_baseline_counts_become_null(): |
| 524 | + instance = _make_params_execution_sql() |
| 525 | + params = instance._get_params(_make_td(test_type="Missing_Pct", baseline_ct=None, baseline_value_ct=None)) |
| 526 | + assert params["BASELINE_CT"] == "NULL" |
| 527 | + assert params["BASELINE_VALUE_CT"] == "NULL" |
| 528 | + |
| 529 | + |
| 530 | +def test_get_params_populated_baseline_counts_pass_through(): |
| 531 | + instance = _make_params_execution_sql() |
| 532 | + params = instance._get_params(_make_td(test_type="Missing_Pct", baseline_ct="1000", baseline_value_ct="950")) |
| 533 | + assert params["BASELINE_CT"] == "1000" |
| 534 | + assert params["BASELINE_VALUE_CT"] == "950" |
| 535 | + |
| 536 | + |
| 537 | +def test_get_params_zero_baseline_count_is_not_nulled(): |
| 538 | + """A real 0 is a meaningful value and must not be coerced to NULL.""" |
| 539 | + instance = _make_params_execution_sql() |
| 540 | + params = instance._get_params(_make_td(test_type="Row_Ct_Pct", baseline_ct=0)) |
| 541 | + assert params["BASELINE_CT"] == 0 |
| 542 | + |
| 543 | + |
| 544 | +def test_get_params_empty_numeric_baselines_become_null(): |
| 545 | + """All numeric baseline params render NULL when empty.""" |
| 546 | + instance = _make_params_execution_sql() |
| 547 | + params = instance._get_params(_make_td( |
| 548 | + test_type="Avg_Shift", |
| 549 | + baseline_unique_ct="", baseline_avg="", baseline_sd="", baseline_sum="", |
| 550 | + )) |
| 551 | + assert params["BASELINE_UNIQUE_CT"] == "NULL" |
| 552 | + assert params["BASELINE_AVG"] == "NULL" |
| 553 | + assert params["BASELINE_SD"] == "NULL" |
| 554 | + # Non-Freshness test types null-guard BASELINE_SUM (numeric use in Incr_Avg_Shift) |
| 555 | + assert params["BASELINE_SUM"] == "NULL" |
| 556 | + |
| 557 | + |
| 558 | +def test_get_params_freshness_baseline_sum_kept_raw_when_empty(): |
| 559 | + """Freshness_Trend quotes BASELINE_SUM (NULLIF('', '') in template) — must stay empty, not 'NULL'.""" |
| 560 | + instance = _make_params_execution_sql() |
| 561 | + params = instance._get_params(_make_td(test_type="Freshness_Trend", baseline_sum="")) |
| 562 | + assert params["BASELINE_SUM"] == "" |
| 563 | + |
| 564 | + |
| 565 | +def test_get_params_baseline_value_left_unguarded(): |
| 566 | + """BASELINE_VALUE has non-uniform usage (quoted/number/IN-list) — not coerced to NULL.""" |
| 567 | + instance = _make_params_execution_sql() |
| 568 | + params = instance._get_params(_make_td(test_type="Constant", baseline_value="")) |
| 569 | + assert params["BASELINE_VALUE"] == "" |
| 570 | + |
| 571 | + |
| 572 | +def test_get_params_empty_tolerances_become_null(): |
| 573 | + """Tolerances use the same NULL guard.""" |
| 574 | + instance = _make_params_execution_sql() |
| 575 | + params = instance._get_params(_make_td(test_type="Volume_Trend", lower_tolerance="", upper_tolerance="")) |
| 576 | + assert params["LOWER_TOLERANCE"] == "NULL" |
| 577 | + assert params["UPPER_TOLERANCE"] == "NULL" |
| 578 | + |
| 579 | + |
0 commit comments