@@ -1026,6 +1026,97 @@ def test_row_difference_failure() -> None:
10261026 )
10271027
10281028
1029+ def test_index_preservation_with_later_rows () -> None :
1030+ # Test comparison with differences in later rows
1031+ _check_successful_or_raise (
1032+ _create_test (
1033+ body = load_yaml (
1034+ """
1035+ test_foo:
1036+ model: sushi.foo
1037+ inputs:
1038+ raw:
1039+ - id: 1
1040+ value: 100
1041+ - id: 2
1042+ value: 200
1043+ - id: 3
1044+ value: 300
1045+ - id: 4
1046+ value: 400
1047+ outputs:
1048+ query:
1049+ - id: 1
1050+ value: 100
1051+ - id: 2
1052+ value: 200
1053+ - id: 3
1054+ value: 999
1055+ - id: 4
1056+ value: 888
1057+ """
1058+ ),
1059+ test_name = "test_foo" ,
1060+ model = _create_model ("SELECT id, value FROM raw" ),
1061+ context = Context (config = Config (model_defaults = ModelDefaultsConfig (dialect = "duckdb" ))),
1062+ ).run (),
1063+ expected_msg = (
1064+ "AssertionError: Data mismatch (exp: expected, act: actual)\n \n "
1065+ " value \n "
1066+ " exp act\n "
1067+ "2 999.0 300.0\n "
1068+ "3 888.0 400.0\n "
1069+ ),
1070+ )
1071+
1072+ # Test with null values in later rows
1073+ _check_successful_or_raise (
1074+ _create_test (
1075+ body = load_yaml (
1076+ """
1077+ test_foo:
1078+ model: sushi.foo
1079+ inputs:
1080+ raw:
1081+ - id: 1
1082+ value: 100
1083+ - id: 2
1084+ value: 200
1085+ - id: 3
1086+ value: null
1087+ - id: 4
1088+ value: 400
1089+ - id: 5
1090+ value: null
1091+ outputs:
1092+ query:
1093+ - id: 1
1094+ value: 100
1095+ - id: 2
1096+ value: 200
1097+ - id: 3
1098+ value: 300
1099+ - id: 4
1100+ value: null
1101+ - id: 5
1102+ value: 500
1103+ """
1104+ ),
1105+ test_name = "test_foo" ,
1106+ model = _create_model ("SELECT id, value FROM raw" ),
1107+ context = Context (config = Config (model_defaults = ModelDefaultsConfig (dialect = "duckdb" ))),
1108+ ).run (),
1109+ expected_msg = (
1110+ "AssertionError: Data mismatch (exp: expected, act: actual)\n \n "
1111+ " value \n "
1112+ " exp act\n "
1113+ "2 300.0 NaN\n "
1114+ "3 NaN 400.0\n "
1115+ "4 500.0 NaN\n "
1116+ ),
1117+ )
1118+
1119+
10291120def test_unknown_column_error () -> None :
10301121 _check_successful_or_raise (
10311122 _create_test (
@@ -2277,7 +2368,7 @@ def test_test_output(tmp_path: Path) -> None:
22772368┃ ┃ item_id: ┃ ┃ num_orders: ┃ num_orders: ┃
22782369┃ Row ┃ Expected ┃ item_id: Actual ┃ Expected ┃ Actual ┃
22792370┡━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
2280- │ 0 │ 4.0 │ 2.0 │ 3.0 │ 1.0 │
2371+ │ 1 │ 4.0 │ 2.0 │ 3.0 │ 1.0 │
22812372└─────┴─────────────────┴─────────────────┴─────────────────┴──────────────────┘
22822373
22832374----------------------------------------------------------------------"""
@@ -2300,14 +2391,14 @@ def test_test_output(tmp_path: Path) -> None:
23002391┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
23012392┃ Row ┃ Expected ┃ Actual ┃
23022393┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
2303- │ 0 │ 4.0 │ 2.0 │
2394+ │ 1 │ 4.0 │ 2.0 │
23042395└─────────────┴────────────────────────┴───────────────────┘
23052396
23062397 Column 'num_orders' mismatch
23072398┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
23082399┃ Row ┃ Expected ┃ Actual ┃
23092400┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
2310- │ 0 │ 3.0 │ 1.0 │
2401+ │ 1 │ 3.0 │ 1.0 │
23112402└─────────────┴────────────────────────┴───────────────────┘
23122403
23132404----------------------------------------------------------------------"""
@@ -2386,6 +2477,56 @@ def test_test_output(tmp_path: Path) -> None:
23862477 in captured_output .stdout
23872478 )
23882479
2480+ # Case 5: Test null value difference in the 3rd row (index 2)
2481+ rmtree (tmp_path / "tests" )
2482+ tests_dir = tmp_path / "tests"
2483+ tests_dir .mkdir ()
2484+
2485+ null_test_file = tmp_path / "tests" / "test_null_in_third_row.yaml"
2486+ null_test_file .write_text (
2487+ """
2488+ test_null_third_row:
2489+ model: sqlmesh_example.full_model
2490+ description: Test null value in third row
2491+ inputs:
2492+ sqlmesh_example.incremental_model:
2493+ rows:
2494+ - id: 1
2495+ item_id: 1
2496+ - id: 2
2497+ item_id: 1
2498+ - id: 3
2499+ item_id: 2
2500+ - id: 4
2501+ item_id: 3
2502+ outputs:
2503+ query:
2504+ rows:
2505+ - item_id: 1
2506+ num_orders: 2
2507+ - item_id: 2
2508+ num_orders: 1
2509+ - item_id: 3
2510+ num_orders: null
2511+ """
2512+ )
2513+
2514+ with capture_output () as captured_output :
2515+ context .test ()
2516+
2517+ output = captured_output .stdout
2518+
2519+ # Check for null value difference in the 3rd row (index 2)
2520+ assert (
2521+ """
2522+ ┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
2523+ ┃ Row ┃ num_orders: Expected ┃ num_orders: Actual ┃
2524+ ┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
2525+ │ 2 │ nan │ 1.0 │
2526+ └──────┴───────────────────────────┴───────────────────────┘"""
2527+ in output
2528+ )
2529+
23892530
23902531@use_terminal_console
23912532def test_test_output_with_invalid_model_name (tmp_path : Path ) -> None :
0 commit comments