|
19 | 19 | from sqlglot import exp |
20 | 20 | from sqlglot.expressions import DataType |
21 | 21 | import re |
| 22 | +from IPython.utils.capture import capture_output |
| 23 | + |
22 | 24 |
|
23 | 25 | from sqlmesh import CustomMaterialization |
24 | 26 | from sqlmesh.cli.example_project import init_example_project |
|
62 | 64 | SnapshotTableInfo, |
63 | 65 | ) |
64 | 66 | from sqlmesh.utils.date import TimeLike, now, to_date, to_datetime, to_timestamp |
65 | | -from sqlmesh.utils.errors import NoChangesPlanError, SQLMeshError |
| 67 | +from sqlmesh.utils.errors import NoChangesPlanError, SQLMeshError, PlanError |
66 | 68 | from sqlmesh.utils.pydantic import validate_string |
67 | 69 | from tests.conftest import DuckDBMetadata, SushiDataValidator |
68 | 70 | from tests.utils.test_helpers import use_terminal_console |
| 71 | +from tests.utils.test_filesystem import create_temp_file |
69 | 72 |
|
70 | 73 | if t.TYPE_CHECKING: |
71 | 74 | from sqlmesh import QueryOrDF |
@@ -6085,3 +6088,42 @@ def test_destroy(copy_to_temp_path): |
6085 | 6088 |
|
6086 | 6089 | # Ensure the cache has been removed |
6087 | 6090 | assert not cache_path.exists() |
| 6091 | + |
| 6092 | + |
| 6093 | +@use_terminal_console |
| 6094 | +def test_audits_running_on_metadata_changes(tmp_path: Path): |
| 6095 | + def setup_senario(model_before: str, model_after: str): |
| 6096 | + models_dir = Path("models") |
| 6097 | + create_temp_file(tmp_path, models_dir / "test.sql", model_before) |
| 6098 | + |
| 6099 | + # Create first snapshot |
| 6100 | + context = Context(paths=tmp_path, config=Config()) |
| 6101 | + context.plan("prod", no_prompts=True, auto_apply=True) |
| 6102 | + |
| 6103 | + # Create second (metadata) snapshot |
| 6104 | + create_temp_file(tmp_path, models_dir / "test.sql", model_after) |
| 6105 | + context.load() |
| 6106 | + |
| 6107 | + with capture_output() as output: |
| 6108 | + with pytest.raises(PlanError): |
| 6109 | + context.plan("prod", no_prompts=True, auto_apply=True) |
| 6110 | + |
| 6111 | + assert 'Failed models\n\n "model"' in output.stdout |
| 6112 | + |
| 6113 | + return output |
| 6114 | + |
| 6115 | + # Ensure incorrect audits (bad data, incorrect definition etc) are evaluated immediately |
| 6116 | + output = setup_senario( |
| 6117 | + "MODEL (name model); SELECT NULL AS col", |
| 6118 | + "MODEL (name model, audits (not_null(columns=[col]))); SELECT NULL AS col", |
| 6119 | + ) |
| 6120 | + assert "'not_null' audit error: 1 row failed" in output.stdout |
| 6121 | + |
| 6122 | + output = setup_senario( |
| 6123 | + "MODEL (name model); SELECT NULL AS col", |
| 6124 | + "MODEL (name model, audits (not_null(columns=[this_col_does_not_exist]))); SELECT NULL AS col", |
| 6125 | + ) |
| 6126 | + assert ( |
| 6127 | + 'Binder Error: Referenced column "this_col_does_not_exist" not found in \nFROM clause!' |
| 6128 | + in output.stdout |
| 6129 | + ) |
0 commit comments