Skip to content

Commit 491462c

Browse files
Fix: Create test fails being generated with null upstream values
1 parent dd73bb7 commit 491462c

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

sqlmesh/core/test/definition.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ def shortDescription(self) -> t.Optional[str]:
151151

152152
def setUp(self) -> None:
153153
"""Load all input tables"""
154+
import pandas as pd
155+
import numpy as np
156+
154157
self.engine_adapter.create_schema(self._qualified_fixture_schema)
155158

156159
for name, values in self.body.get("inputs", {}).items():
@@ -201,6 +204,10 @@ def setUp(self) -> None:
201204
else:
202205
query_or_df = self._create_df(values, columns=columns_to_known_types)
203206

207+
# Convert NaN/NaT values to None if DataFrame
208+
if isinstance(query_or_df, pd.DataFrame):
209+
query_or_df = query_or_df.replace({np.nan: None})
210+
204211
self.engine_adapter.create_view(
205212
self._test_fixture_table(name), query_or_df, columns_to_known_types
206213
)

tests/core/test_test.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,3 +2753,64 @@ def test_disable_test_logging_if_no_tests_found(mocker: MockerFixture, tmp_path:
27532753

27542754
output = captured_output.stdout
27552755
assert "test" not in output.lower()
2756+
2757+
2758+
def test_test_generation_with_timestamp_nat(tmp_path: Path) -> None:
2759+
init_example_project(tmp_path, engine_type="duckdb")
2760+
2761+
config = Config(
2762+
default_connection=DuckDBConnectionConfig(),
2763+
model_defaults=ModelDefaultsConfig(dialect="duckdb"),
2764+
)
2765+
foo_sql_file = tmp_path / "models" / "foo.sql"
2766+
foo_sql_file.write_text(
2767+
"MODEL (name sqlmesh_example.foo); SELECT ts_col FROM sqlmesh_example.bar;"
2768+
)
2769+
bar_sql_file = tmp_path / "models" / "bar.sql"
2770+
bar_sql_file.write_text("MODEL (name sqlmesh_example.bar); SELECT ts_col FROM external_table;")
2771+
2772+
context = Context(paths=tmp_path, config=config)
2773+
2774+
# This simulates the scenario where upstream models have NULL timestamp values
2775+
input_queries = {
2776+
"sqlmesh_example.bar": """
2777+
SELECT ts_col FROM (
2778+
VALUES
2779+
(TIMESTAMP '2024-09-20 11:30:00.123456789'),
2780+
(CAST(NULL AS TIMESTAMP)),
2781+
(TIMESTAMP '2024-09-21 15:45:00.987654321')
2782+
) AS t(ts_col)
2783+
"""
2784+
}
2785+
2786+
# This should not raise an exception even with NULL timestamp values
2787+
context.create_test("sqlmesh_example.foo", input_queries=input_queries, overwrite=True)
2788+
2789+
test = load_yaml(context.path / c.TESTS / "test_foo.yaml")
2790+
assert len(test) == 1
2791+
assert "test_foo" in test
2792+
2793+
# Verify that the test was created with correct input and output data
2794+
inputs = test["test_foo"]["inputs"]
2795+
outputs = test["test_foo"]["outputs"]
2796+
2797+
# Check that we have the expected input table
2798+
assert '"memory"."sqlmesh_example"."bar"' in inputs
2799+
bar_data = inputs['"memory"."sqlmesh_example"."bar"']
2800+
2801+
# Verify we have 3 rows (2 with timestamps, 1 with NULL)
2802+
assert len(bar_data) == 3
2803+
2804+
# Verify that non-NULL timestamps are preserved
2805+
assert bar_data[0]["ts_col"] == datetime.datetime(2024, 9, 20, 11, 30, 0, 123456)
2806+
assert bar_data[2]["ts_col"] == datetime.datetime(2024, 9, 21, 15, 45, 0, 987654)
2807+
2808+
# Verify that NULL timestamp is represented as None (not NaT)
2809+
assert bar_data[1]["ts_col"] is None
2810+
2811+
# Verify that the output matches the input (since the model just selects from bar)
2812+
query_output = outputs["query"]
2813+
assert len(query_output) == 3
2814+
assert query_output[0]["ts_col"] == datetime.datetime(2024, 9, 20, 11, 30, 0, 123456)
2815+
assert query_output[1]["ts_col"] is None
2816+
assert query_output[2]["ts_col"] == datetime.datetime(2024, 9, 21, 15, 45, 0, 987654)

0 commit comments

Comments
 (0)