Eason09053360 opened a new pull request, #73112:
URL: https://github.com/apache/airflow/pull/73112

   ## Why
   
   `StructlogCapture.__contains__` backs the `cap_structlog` fixture, which 
`caplog` is replaced by on Airflow 3.1+, so it is what every structured log 
assertion in the repo goes through.
   
   Its dict branch built the lookup with `operator.itemgetter(*target.keys())`, 
whose return type depends on how many keys it is given: a tuple for two or 
more, but a **bare value** for one. The expected side is always a tuple, so for 
a single-key target `zip(got, want)` iterated that bare value instead of 
pairing it up — for a string, comparing its first character against the whole 
expected string:
   
   ```python
   got  = "some event"                 # str, not a tuple
   want = ("some event",)
   zip(got, want)  # -> [("s", "some event")]  -> False
   ```
   
   A single-field assertion therefore never matched, whatever was logged:
   
   ```python
   assert {"event": "some event", "field1": False} in caplog  # True
   assert {"event": "some event"} in caplog                   # False, even 
though it was logged
   ```
   
   This is a false negative, which is the worst failure mode for a test helper 
— the natural reading of the red test is that the assertion is wrong, and the 
way out is `caplog.text` or a mocked logger, the two patterns 
`contributing-docs` asks us to stop using. The `cap_structlog` docstring itself 
demonstrates `assert {"field2": [1, 2]} in cap_structlog`, so the documented 
example was one of the broken cases. Grepping the repo, there is not a single 
one-key dict assertion today.
   
   ## What
   
   `devel-common/src/tests_common/test_utils/logs.py` builds the actual values 
with `tuple(e[key] for key in target)` instead, which keys off the same dict as 
`want` and so keeps the two aligned at any number of keys. A missing key still 
raises `KeyError` inside the existing `try` and counts as a non-match.
   
   An empty dict is now rejected with `ValueError`. `itemgetter()` used to 
raise `TypeError` on zero keys, and losing that would have turned `assert 
expected in caplog` into a vacuous pass whenever a dynamically built `expected` 
came out empty.
   
   `StructlogCapture` had no tests; 
`devel-common/tests/unit/tests_common/test_utils/test_logs.py` covers the dict 
branch — the single-key cases (including the docstring's and a `re.Pattern` 
value) fail without this change, and the negative cases pin down that partial 
and missing-key targets still do not match.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   
   Generated-by: Claude Code (Opus 5) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


-- 
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