@@ -1026,6 +1026,97 @@ def test_row_difference_failure() -> None:
1026
1026
)
1027
1027
1028
1028
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
+
1029
1120
def test_unknown_column_error () -> None :
1030
1121
_check_successful_or_raise (
1031
1122
_create_test (
@@ -2277,7 +2368,7 @@ def test_test_output(tmp_path: Path) -> None:
2277
2368
┃ ┃ item_id: ┃ ┃ num_orders: ┃ num_orders: ┃
2278
2369
┃ Row ┃ Expected ┃ item_id: Actual ┃ Expected ┃ Actual ┃
2279
2370
┡━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
2280
- │ 0 │ 4.0 │ 2.0 │ 3.0 │ 1.0 │
2371
+ │ 1 │ 4.0 │ 2.0 │ 3.0 │ 1.0 │
2281
2372
└─────┴─────────────────┴─────────────────┴─────────────────┴──────────────────┘
2282
2373
2283
2374
----------------------------------------------------------------------"""
@@ -2300,14 +2391,14 @@ def test_test_output(tmp_path: Path) -> None:
2300
2391
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
2301
2392
┃ Row ┃ Expected ┃ Actual ┃
2302
2393
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
2303
- │ 0 │ 4.0 │ 2.0 │
2394
+ │ 1 │ 4.0 │ 2.0 │
2304
2395
└─────────────┴────────────────────────┴───────────────────┘
2305
2396
2306
2397
Column 'num_orders' mismatch
2307
2398
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
2308
2399
┃ Row ┃ Expected ┃ Actual ┃
2309
2400
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
2310
- │ 0 │ 3.0 │ 1.0 │
2401
+ │ 1 │ 3.0 │ 1.0 │
2311
2402
└─────────────┴────────────────────────┴───────────────────┘
2312
2403
2313
2404
----------------------------------------------------------------------"""
@@ -2386,6 +2477,56 @@ def test_test_output(tmp_path: Path) -> None:
2386
2477
in captured_output .stdout
2387
2478
)
2388
2479
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
+
2389
2530
2390
2531
@use_terminal_console
2391
2532
def test_test_output_with_invalid_model_name (tmp_path : Path ) -> None :
0 commit comments