Skip to content

Commit c8ae8a8

Browse files
authored
Chore: Minor refactors in sqlmesh test output (#4755)
1 parent 461fb79 commit c8ae8a8

File tree

5 files changed

+56
-55
lines changed

5 files changed

+56
-55
lines changed

sqlmesh/core/console.py

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,26 +1957,29 @@ def log_test_results(self, result: ModelTextTestResult, target_dialect: str) ->
19571957
divider_length = 70
19581958

19591959
self._log_test_details(result)
1960-
self._print("\n")
19611960

1961+
message = (
1962+
f"Ran {result.testsRun} tests against {target_dialect} in {result.duration} seconds."
1963+
)
19621964
if result.wasSuccessful():
19631965
self._print("=" * divider_length)
19641966
self._print(
1965-
f"Successfully Ran {str(result.testsRun)} tests against {target_dialect}",
1967+
f"Successfully {message}",
19661968
style="green",
19671969
)
19681970
self._print("-" * divider_length)
19691971
else:
19701972
self._print("-" * divider_length)
1971-
self._print("Test Failure Summary")
1973+
self._print("Test Failure Summary", style="red")
19721974
self._print("=" * divider_length)
1973-
self._print(
1974-
f"Num Successful Tests: {result.testsRun - len(result.failures) - len(result.errors)}"
1975-
)
1975+
failures = len(result.failures) + len(result.errors)
1976+
self._print(f"{message} \n")
1977+
1978+
self._print(f"Failed tests ({failures}):")
19761979
for test, _ in result.failures + result.errors:
19771980
if isinstance(test, ModelTest):
1978-
self._print(f"Failure Test: {test.path}::{test.test_name}")
1979-
self._print("=" * divider_length)
1981+
self._print(f" {test.path}::{test.test_name}")
1982+
self._print("=" * divider_length, end="\n\n")
19801983

19811984
def _captured_unit_test_results(self, result: ModelTextTestResult) -> str:
19821985
with self.console.capture() as capture:
@@ -2499,19 +2502,24 @@ def show_linter_violations(
24992502
else:
25002503
self.log_warning(msg)
25012504

2502-
def _log_test_details(self, result: ModelTextTestResult) -> None:
2505+
def _log_test_details(
2506+
self, result: ModelTextTestResult, unittest_char_separator: bool = True
2507+
) -> None:
25032508
"""
25042509
This is a helper method that encapsulates the logic for logging the relevant unittest for the result.
25052510
The top level method (`log_test_results`) reuses `_log_test_details` differently based on the console.
25062511
25072512
Args:
25082513
result: The unittest test result that contains metrics like num success, fails, ect.
25092514
"""
2510-
tests_run = result.testsRun
2515+
2516+
if result.wasSuccessful():
2517+
self._print("\n", end="")
2518+
return
2519+
25112520
errors = result.errors
25122521
failures = result.failures
25132522
skipped = result.skipped
2514-
is_success = not (errors or failures)
25152523

25162524
infos = []
25172525
if failures:
@@ -2521,12 +2529,13 @@ def _log_test_details(self, result: ModelTextTestResult) -> None:
25212529
if skipped:
25222530
infos.append(f"skipped={skipped}")
25232531

2524-
self._print("\n", end="")
2532+
if unittest_char_separator:
2533+
self._print(f"\n{unittest.TextTestResult.separator1}\n\n", end="")
25252534

25262535
for (test_case, failure), test_failure_tables in zip_longest( # type: ignore
25272536
failures, result.failure_tables
25282537
):
2529-
self._print(unittest.TextTestResult.separator1)
2538+
self._print(unittest.TextTestResult.separator2)
25302539
self._print(f"FAIL: {test_case}")
25312540

25322541
if test_description := test_case.shortDescription():
@@ -2541,21 +2550,11 @@ def _log_test_details(self, result: ModelTextTestResult) -> None:
25412550
self._print("\n", end="")
25422551

25432552
for test_case, error in errors:
2544-
self._print(unittest.TextTestResult.separator1)
2553+
self._print(unittest.TextTestResult.separator2)
25452554
self._print(f"ERROR: {test_case}")
25462555
self._print(f"{unittest.TextTestResult.separator2}")
25472556
self._print(error)
25482557

2549-
# Output final report
2550-
self._print(unittest.TextTestResult.separator2)
2551-
test_duration_msg = f" in {result.duration:.3f}s" if result.duration else ""
2552-
self._print(
2553-
f"\nRan {tests_run} {'tests' if tests_run > 1 else 'test'}{test_duration_msg} \n"
2554-
)
2555-
self._print(
2556-
f"{'OK' if is_success else 'FAILED'}{' (' + ', '.join(infos) + ')' if infos else ''}"
2557-
)
2558-
25592558

25602559
def _cells_match(x: t.Any, y: t.Any) -> bool:
25612560
"""Helper function to compare two cells and returns true if they're equal, handling array objects."""
@@ -2836,14 +2835,19 @@ def log_test_results(self, result: ModelTextTestResult, target_dialect: str) ->
28362835
"font-weight": "bold",
28372836
"font-family": "Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace",
28382837
}
2838+
2839+
message = (
2840+
f"Ran {result.testsRun} tests against {target_dialect} in {result.duration} seconds."
2841+
)
2842+
28392843
if result.wasSuccessful():
28402844
success_color = {"color": "#008000"}
28412845
header = str(h("span", {"style": shared_style}, "-" * divider_length))
28422846
message = str(
28432847
h(
28442848
"span",
28452849
{"style": {**shared_style, **success_color}},
2846-
f"Successfully Ran {str(result.testsRun)} tests against {target_dialect}",
2850+
f"Successfully {message}",
28472851
)
28482852
)
28492853
footer = str(h("span", {"style": shared_style}, "=" * divider_length))
@@ -2855,31 +2859,31 @@ def log_test_results(self, result: ModelTextTestResult, target_dialect: str) ->
28552859
fail_shared_style = {**shared_style, **fail_color}
28562860
header = str(h("span", {"style": fail_shared_style}, "-" * divider_length))
28572861
message = str(h("span", {"style": fail_shared_style}, "Test Failure Summary"))
2858-
num_success = str(
2859-
h(
2860-
"span",
2861-
{"style": fail_shared_style},
2862-
f"Num Successful Tests: {result.testsRun - len(result.failures) - len(result.errors)}",
2862+
failed_tests = [
2863+
str(
2864+
h(
2865+
"span",
2866+
{"style": fail_shared_style},
2867+
f"Failed tests ({len(result.failures) + len(result.errors)}):",
2868+
)
28632869
)
2864-
)
2865-
failure_tests = []
2870+
]
2871+
28662872
for test, _ in result.failures + result.errors:
28672873
if isinstance(test, ModelTest):
2868-
failure_tests.append(
2874+
failed_tests.append(
28692875
str(
28702876
h(
28712877
"span",
28722878
{"style": fail_shared_style},
2873-
f"Failure Test: {test.model.name} {test.test_name}",
2879+
f" {test.model.name}::{test.test_name}",
28742880
)
28752881
)
28762882
)
2877-
failures = "<br>".join(failure_tests)
2883+
failures = "<br>".join(failed_tests)
28782884
footer = str(h("span", {"style": fail_shared_style}, "=" * divider_length))
28792885
error_output = widgets.Textarea(output, layout={"height": "300px", "width": "100%"})
2880-
test_info = widgets.HTML(
2881-
"<br>".join([header, message, footer, num_success, failures, footer])
2882-
)
2886+
test_info = widgets.HTML("<br>".join([header, message, footer, failures, footer]))
28832887
self.display(widgets.VBox(children=[test_info, error_output], layout={"width": "100%"}))
28842888

28852889

@@ -3202,21 +3206,21 @@ def log_success(self, message: str) -> None:
32023206
self._print(message)
32033207

32043208
def log_test_results(self, result: ModelTextTestResult, target_dialect: str) -> None:
3209+
message = f"Ran `{result.testsRun}` Tests Against `{target_dialect}`"
3210+
32053211
if result.wasSuccessful():
3206-
self._print(
3207-
f"**Successfully Ran `{str(result.testsRun)}` Tests Against `{target_dialect}`**\n\n"
3208-
)
3212+
self._print(f"**Successfully {message}**\n\n")
32093213
else:
32103214
self._print("```")
3211-
self._log_test_details(result)
3215+
self._log_test_details(result, unittest_char_separator=False)
32123216
self._print("```\n\n")
32133217

3214-
self._print(
3215-
f"**Num Successful Tests: {result.testsRun - len(result.failures) - len(result.errors)}**\n\n"
3216-
)
3218+
failures = len(result.failures) + len(result.errors)
3219+
self._print(f"**{message}**\n")
3220+
self._print(f"**Failed tests ({failures}):**")
32173221
for test, _ in result.failures + result.errors:
32183222
if isinstance(test, ModelTest):
3219-
self._print(f"* Failure Test: `{test.model.name}` - `{test.test_name}`\n\n")
3223+
self._print(f"`{test.model.name}`::`{test.test_name}`\n\n")
32203224

32213225
def log_skipped_models(self, snapshot_names: t.Set[str]) -> None:
32223226
if snapshot_names:

sqlmesh/core/test/runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,6 @@ def _run_single_test(
174174

175175
end_time = time.perf_counter()
176176

177-
combined_results.duration = end_time - start_time
177+
combined_results.duration = round(end_time - start_time, 2)
178178

179179
return combined_results

tests/core/test_test.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,7 +2281,7 @@ def test_test_output(tmp_path: Path) -> None:
22812281
)
22822282

22832283
assert "Ran 2 tests" in output
2284-
assert "FAILED (failures=1)" in output
2284+
assert "Failed tests (1):" in output
22852285

22862286
# Case 2: Ensure that the verbose log report is structured correctly
22872287
with capture_output() as captured_output:
@@ -2321,7 +2321,7 @@ def test_test_output(tmp_path: Path) -> None:
23212321
output = captured_output.stdout
23222322

23232323
assert "Ran 102 tests" in output
2324-
assert "FAILED (failures=51)" in output
2324+
assert "Failed tests (51):" in output
23252325

23262326
# Case 4: Test that wide tables are split into even chunks for default verbosity
23272327
rmtree(tmp_path / "tests")
@@ -2426,11 +2426,7 @@ def test_test_output_with_invalid_model_name(tmp_path: Path) -> None:
24262426
f"""Model '"invalid_model"' was not found at {wrong_test_file}"""
24272427
in mock_logger.call_args[0][0]
24282428
)
2429-
assert (
2430-
".\n----------------------------------------------------------------------\n\nRan 1 test in"
2431-
in output.stdout
2432-
)
2433-
assert "OK" in output.stdout
2429+
assert "Successfully Ran 1 test" in output.stdout
24342430

24352431

24362432
def test_number_of_tests_found(tmp_path: Path) -> None:

tests/integrations/github/cicd/test_github_commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ def test_run_all_test_failed(
477477
assert (
478478
"""sqlmesh.utils.errors.TestError: some error""" in test_checks_runs[2]["output"]["summary"]
479479
)
480-
assert """**Num Successful Tests: 0**""" in test_checks_runs[2]["output"]["summary"]
480+
assert """Failed tests (1):""" in test_checks_runs[2]["output"]["summary"]
481481

482482
assert "SQLMesh - Prod Plan Preview" in controller._check_run_mapping
483483
prod_plan_preview_checks_runs = controller._check_run_mapping[

tests/integrations/github/cicd/test_integration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,7 @@ def test_pr_delete_model(
18531853
assert GithubCheckStatus(test_checks_runs[2]["status"]).is_completed
18541854
assert GithubCheckConclusion(test_checks_runs[2]["conclusion"]).is_success
18551855
assert test_checks_runs[2]["output"]["title"] == "Tests Passed"
1856+
print(test_checks_runs[2]["output"]["summary"])
18561857
assert (
18571858
test_checks_runs[2]["output"]["summary"].strip()
18581859
== "**Successfully Ran `3` Tests Against `duckdb`**"

0 commit comments

Comments
 (0)