881. Only the endpoint's own task types are returned (validation vs. profile).
992. The validation feed honours the caller's catalog access.
10103. The result is bounded at _RECENT_FAILURES_LIMIT with the minimal RunFailureOut shape.
11- 4. The run table is queried only for runs whose config was staged out of the
12- job parameters, and never otherwise.
11+ 4. Neither feed ever queries the SQL warehouse.
1312"""
1413
1514from unittest .mock import MagicMock , create_autospec
2726)
2827from databricks_labs_dqx_app .backend .services .job_service import JobService
2928from databricks_labs_dqx_app .backend .services .task_runner_runs import TaskRunnerRun
30- from databricks_labs_dqx_app .backend .sql_executor import SqlExecutor
3129
3230
3331def _failed_run (
@@ -50,67 +48,58 @@ def _failed_run(
5048
5149@pytest .fixture
5250def job_service_mock () -> MagicMock :
53- svc = create_autospec (JobService , instance = True )
54- svc .lookup_source_tables .return_value = {}
55- return svc
51+ return create_autospec (JobService , instance = True )
5652
5753
58- @pytest .fixture
59- def sql_executor () -> MagicMock :
60- sql = create_autospec (SqlExecutor , instance = True )
61- sql .fqn .side_effect = lambda name : f"dqx.dqx_studio.{ name } "
62- return sql
63-
64-
65- async def _validation (job_svc : MagicMock , sql : MagicMock , catalogs : frozenset [str ] = frozenset ({"main" })):
66- return await list_recent_validation_failures (job_svc = job_svc , user_catalogs = catalogs , sql = sql )
54+ async def _validation (job_svc : MagicMock , catalogs : frozenset [str ] = frozenset ({"main" })):
55+ return await list_recent_validation_failures (job_svc = job_svc , user_catalogs = catalogs )
6756
6857
6958class TestListRecentValidationFailures :
70- async def test_returns_only_validation_task_types (self , job_service_mock , sql_executor ):
59+ async def test_returns_only_validation_task_types (self , job_service_mock ):
7160 job_service_mock .list_recent_failed_runs .return_value = [
7261 _failed_run ("run-dryrun" ),
7362 _failed_run ("run-scheduled" , task_type = "scheduled" ),
7463 _failed_run ("run-profile" , task_type = "profile" ),
7564 ]
7665
77- result = await _validation (job_service_mock , sql_executor )
66+ result = await _validation (job_service_mock )
7867
7968 assert [r .run_id for r in result ] == ["run-dryrun" , "run-scheduled" ]
8069 assert all (r .status == "FAILED" for r in result )
8170
82- async def test_excludes_runs_from_inaccessible_catalogs (self , job_service_mock , sql_executor ):
71+ async def test_excludes_runs_from_inaccessible_catalogs (self , job_service_mock ):
8372 job_service_mock .list_recent_failed_runs .return_value = [
8473 _failed_run ("run-visible" , fqn = "main.public.orders" ),
8574 _failed_run ("run-hidden" , fqn = "restricted.public.orders" ),
8675 ]
8776
88- result = await _validation (job_service_mock , sql_executor )
77+ result = await _validation (job_service_mock )
8978
9079 assert [r .run_id for r in result ] == ["run-visible" ]
9180
92- async def test_includes_sql_check_prefix_runs (self , job_service_mock , sql_executor ):
81+ async def test_includes_sql_check_prefix_runs (self , job_service_mock ):
9382 job_service_mock .list_recent_failed_runs .return_value = [
9483 _failed_run ("run-sql" , fqn = "__sql_check__/my_check" ),
9584 ]
9685
97- result = await _validation (job_service_mock , sql_executor , catalogs = frozenset ())
86+ result = await _validation (job_service_mock , catalogs = frozenset ())
9887
9988 assert [r .source_table_fqn for r in result ] == ["__sql_check__/my_check" ]
10089
101- async def test_result_bounded_at_limit (self , job_service_mock , sql_executor ):
90+ async def test_result_bounded_at_limit (self , job_service_mock ):
10291 job_service_mock .list_recent_failed_runs .return_value = [
10392 _failed_run (f"f-{ i } " ) for i in range (DRYRUN_LIMIT + 10 )
10493 ]
10594
106- result = await _validation (job_service_mock , sql_executor )
95+ result = await _validation (job_service_mock )
10796
10897 assert len (result ) == DRYRUN_LIMIT
10998
110- async def test_returns_minimal_fields_only (self , job_service_mock , sql_executor ):
99+ async def test_returns_minimal_fields_only (self , job_service_mock ):
111100 job_service_mock .list_recent_failed_runs .return_value = [_failed_run ("run-failed" )]
112101
113- result = await _validation (job_service_mock , sql_executor )
102+ result = await _validation (job_service_mock )
114103
115104 assert result == [
116105 RunFailureOut (
@@ -121,39 +110,22 @@ async def test_returns_minimal_fields_only(self, job_service_mock, sql_executor)
121110 )
122111 ]
123112
124- async def test_never_queries_the_warehouse_when_configs_are_inline (self , job_service_mock , sql_executor ):
125- job_service_mock .list_recent_failed_runs .return_value = [_failed_run ("run-failed" )]
126-
127- await _validation (job_service_mock , sql_executor )
128-
129- job_service_mock .lookup_source_tables .assert_not_called ()
130- sql_executor .query .assert_not_called ()
131- sql_executor .query_dicts .assert_not_called ()
132-
133- async def test_staged_config_runs_resolve_their_table_from_the_run_table (self , job_service_mock , sql_executor ):
113+ async def test_runs_without_a_source_table_are_skipped (self , job_service_mock ):
114+ # The catalog filter cannot be applied to a run with no table, so it
115+ # is dropped rather than shown to everyone.
134116 job_service_mock .list_recent_failed_runs .return_value = [
135- _failed_run ("run-inline" ),
136- _failed_run ("run-staged" , fqn = None ),
117+ _failed_run ("run-known" ),
137118 _failed_run ("run-unknown" , fqn = None ),
138119 ]
139- job_service_mock .lookup_source_tables .return_value = {"run-staged" : "main.public.big" }
140-
141- result = await _validation (job_service_mock , sql_executor )
142-
143- job_service_mock .lookup_source_tables .assert_called_once_with (
144- "dqx.dqx_studio.dq_validation_runs" , ["run-staged" , "run-unknown" ]
145- )
146- # A staged run whose table cannot be resolved is dropped (the catalog
147- # filter cannot be applied to it).
148- assert [(r .run_id , r .source_table_fqn ) for r in result ] == [
149- ("run-inline" , "main.public.orders" ),
150- ("run-staged" , "main.public.big" ),
151- ]
152120
153- async def test_empty_list_when_no_failures (self , job_service_mock , sql_executor ):
121+ result = await _validation (job_service_mock )
122+
123+ assert [r .run_id for r in result ] == ["run-known" ]
124+
125+ async def test_empty_list_when_no_failures (self , job_service_mock ):
154126 job_service_mock .list_recent_failed_runs .return_value = []
155127
156- assert await _validation (job_service_mock , sql_executor ) == []
128+ assert await _validation (job_service_mock ) == []
157129
158130
159131class TestListRecentProfileFailures :
@@ -189,7 +161,6 @@ async def test_returns_minimal_fields_only(self, job_service_mock):
189161 created_at = "2026-09-21T14:13:20+00:00" ,
190162 )
191163 ]
192- job_service_mock .lookup_source_tables .assert_not_called ()
193164
194165 async def test_empty_list_when_no_failures (self , job_service_mock ):
195166 job_service_mock .list_recent_failed_runs .return_value = []
0 commit comments