moomindani commented on code in PR #70831:
URL: https://github.com/apache/airflow/pull/70831#discussion_r3887844766


##########
providers/databricks/tests/unit/databricks/sensors/test_databricks.py:
##########
@@ -69,15 +69,33 @@ def test_init_statement_id(self):
         assert op.warehouse_id == WAREHOUSE_ID
 
     @pytest.mark.parametrize(
-        ("kwargs", "match"),
+        ("statement", "statement_id"),
         [
-            ({"statement": STATEMENT, "statement_id": STATEMENT_ID}, "Cannot 
provide both"),
-            ({}, "One of either statement or statement_id"),
+            (STATEMENT, STATEMENT_ID),
+            (STATEMENT, ""),
         ],
     )
-    def test_statement_combination_validated_at_execute(self, kwargs, match):
-        op = DatabricksSQLStatementsSensor(task_id=TASK_ID, 
warehouse_id=WAREHOUSE_ID, **kwargs)
-        with pytest.raises(AirflowException, match=match):
+    def test_both_statements_included_validated_at_init(self, statement, 
statement_id):
+        with pytest.raises(ValueError, match="Cannot provide both"):
+            DatabricksSQLStatementsSensor(
+                statement=statement,
+                statement_id=statement_id,
+                task_id=TASK_ID,
+                warehouse_id=WAREHOUSE_ID,
+            )
+
+    @pytest.mark.parametrize(
+        ("statement", "statement_id"),
+        [
+            (None, None),
+            ("", None),

Review Comment:
   Good question, and I think the dead-code version actually weakens the guard 
rather than strengthening it.
   
   If the constructor raises, `render_template_fields` and `execute` never run 
— so the block asserts only "something in here raised `ValueError`". Move the 
check back into `execute()` later and the test still passes, which is exactly 
the regression you want it to catch. The stronger form is the opposite: assert 
on the constructor **alone**, with nothing after it. Then if the check moves 
out of `__init__`, the constructor stops raising and the test fails immediately.
   
   ```python
   with pytest.raises(ValueError, match="Provide exactly one of statement or 
statement_id"):
       DatabricksSQLStatementsSensor(
           task_id=TASK_ID, warehouse_id=WAREHOUSE_ID,
           statement=statement, statement_id=statement_id, dag=dag,
       )
   ```
   
   That also discriminates against the old code, which is what my note was 
really asking for. Verified both sides locally with 
`render_template_as_native_obj=True`, `statement="SELECT 1"`, `statement_id="{{ 
None }}"`:
   
   * current main (checks in `execute()`, truthiness): constructs fine, renders 
to `statement_id=None`, and `execute()` proceeds to submit the statement — no 
exception at all.
   * this PR: `ValueError: Cannot provide both statement and statement_id.` 
from the constructor.
   
   So a plain `pytest.raises` around the constructor fails before the change 
and passes after it, which no current test does.
   
   Two smaller points:
   
   The `dag=...` with `render_template_as_native_obj=True` documents the 
scenario but the test does not depend on it — the constructor never renders, so 
it behaves the same without the flag. If you want a test where rendering is 
load-bearing rather than dead code, that is the *other* half, and it is worth 
having as a second test: pass only `statement="{{ None }}"`, construct, 
`render_template_fields`, then assert `execute()` raises. I measured that on 
this PR's head and it gives `ValueError: One of either statement or 
statement_id must be provided.` — the render call there is doing real work, and 
the pair of tests then pins each check to its own site.
   
   Also note your `match=` uses "Provide exactly one of statement or 
statement_id" while the code currently says "Cannot provide both statement and 
statement_id." — that test will fail unless the message change from my other 
comment lands too. Worth doing both in the same push.
   
   ---
   Drafted-by: Claude Code (Opus 5); reviewed by @moomindani before posting
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to