Thank you Ash and Amogh Desai for your insights and explanations.
The information you shared has been incredibly helpful and is contributing
a lot to my growth.

2025년 7월 8일 (화) 오후 2:54, Amogh Desai <amoghdesai....@gmail.com>님이 작성:

> Agreed, I personally also find the current way to be easier to read and in
> most
> cases we want to assert if "something" was called, irrespective of the
> order it was
> called in. So the dedicated function based way works well for me.
>
> If I want to test a order, I'd rather call parts of code that I want to
> test explicitly and assert
> on them.
>
> > This happens because the mock object is not properly recognized as a mock
> instance at type-checking time, which might confuse some contributors,
> especially new ones relying on type hints or static analysis tools.
>
> Regarding this, I'd say you can either cast mocks to their types as one
> way:
> `mock_http_run: MagicMock = mock_http_run` -- give or take, or use
> `autospec` to make the mock reflect the signature of the object? Check out:
> https://docs.python.org/3/library/unittest.mock.html#autospeccing
>
> Thanks & Regards,
> Amogh Desai
>
>
> On Mon, Jul 7, 2025 at 6:13 PM Ash Berlin-Taylor <a...@apache.org> wrote:
>
> > def test_get_account(self, mock_paginate: Mock, mock_http_run: Mocj,
> > conn_id, account_id):
> >
> >
> > Might fix that? IDEs in general do not cope well with purest tests, and
> > are missing context on what most of the variables are, be it
> parameterised
> > values or fixture values, so this isn’t a problem that is unique to
> mocks.
> >
> > > On 7 Jul 2025, at 12:47, Kyungjun Lee <kyungjunlee...@gmail.com>
> wrote:
> > >
> > > I'd like to follow up on our previous discussion about pytest-native vs
> > > unittest-style assertions.
> > >
> > > While working on the following test case:
> > >
> > > ```python
> > >
> > > @pytest.mark.parametrize(
> > >    argnames="conn_id, account_id",
> > >    argvalues=[(ACCOUNT_ID_CONN, None), (NO_ACCOUNT_ID_CONN,
> ACCOUNT_ID)],
> > >    ids=["default_account", "explicit_account"],
> > > )
> > > @patch.object(DbtCloudHook, "run")
> > > @patch.object(DbtCloudHook, "_paginate")
> > > def test_get_account(self, mock_paginate, mock_http_run, conn_id,
> > > account_id):
> > >    hook = DbtCloudHook(conn_id)
> > >    hook.get_account(account_id=account_id)
> > >
> > >    assert hook.method == "GET"
> > >
> > >    _account_id = account_id or DEFAULT_ACCOUNT_ID
> > >    hook.run.assert_called_once_with(
> > >        endpoint=f"api/v2/accounts/{_account_id}/", data=None,
> > > extra_options=None
> > >    )
> > >    hook._paginate.assert_not_called()
> > >
> > > ```
> > >
> > > My IDE shows a warning:
> > > Cannot find reference 'assert_called_once_with' in 'function'.
> > >
> > > This happens because the mock object is not properly recognized as a
> mock
> > > instance at type-checking time, which might confuse some contributors,
> > > especially new ones relying on type hints or static analysis tools.
> > >
> > > I realized that this aspect of mock handling might be missing from our
> > > previous discussions. I wanted to bring it up as part of the broader
> > > conversation about test styles—particularly how we balance IDE/tooling
> > > support with readability and style consistency.
> > >
> > > Curious to hear your thoughts on this!
> > >
> > > @ash @potiuk
> > >
> > > 2025년 7월 6일 (일) 오후 8:09, Kyungjun Lee <kyungjunlee...@gmail.com>님이 작성:
> > >
> > >> Thank you @Potiuk for pointing out the intent behind the “one assert
> per
> > >> test” principle, and @ash for highlighting how using dedicated mock
> > assert
> > >> functions can make the code easier to read and understand. These were
> > >> perspectives I hadn’t fully considered, and I really appreciate you
> > sharing
> > >> them.
> > >>
> > >> Thanks to your input, I was able to read more materials and broaden my
> > >> thinking on the topic. That said, my original focus was more on the
> idea
> > >> that sticking to plain assert statements lowers the entry barrier for
> > new
> > >> contributors—because they don’t have to learn multiple assertion
> styles.
> > >>
> > >> Still, as @Potiuk mentioned, I’ll put more thought into making the
> > testing
> > >> guidelines clearer and more concrete—especially since that helps
> > AI-based
> > >> tools as well 😄
> > >>
> > >> For reference, here’s one of the articles I read:
> > >> https://medium.com/@kentbeck_7670/test-desiderata-94150638a4b3
> > >>
> > >> Thank you to everyone who took part in this discussion.
> > >>
> > >> 2025년 7월 6일 (일) 오후 3:42, Ash Berlin-Taylor <a...@apache.org>님이 작성:
> > >>
> > >>> I personally find the dedicated functions way easier to read the
> intent
> > >>> behind, it’s one function/statement vs 3. More so when you don’t care
> > about
> > >>> the order of calls, just that something was called (where to do this
> > >>> manually we’d need to reimplement the helper function)
> > >>>
> > >>> Additionally pytest already rewrites those to have nicer error
> > messages,
> > >>> but the dedicated mock assert finding are much easier to read the
> code
> > and
> > >>> understand the intent to me, so I’i am for staying with the dedicated
> > >>> assert functions
> > >>>
> > >>> -ash
> > >>>
> > >>>> On 5 Jul 2025, at 13:30, Kyungjun Lee <kyungjunlee...@gmail.com>
> > wrote:
> > >>>>
> > >>>> I’ve learned a lot of things I didn’t know before.
> > >>>> Thank you so much for all your help — I really appreciate it.
> > >>>> I’ll get started on this right away!
> > >>>>
> > >>>> 2025년 7월 5일 (토) 오후 9:18, Jarek Potiuk <ja...@potiuk.com>님이 작성:
> > >>>>
> > >>>>>> Haha ... I'm curious — which part sounded like ChatGPT style?
> > >>>>> English isn't my first language, so I did get a little help from
> it.
> > >>>>>
> > >>>>> That whole paragraph :) .
> > >>>>>
> > >>>>>>> Sure! Since you asked for how the test *should* be written, I
> took
> > >>> the
> > >>>>> opportunity to clean it up using a more pytest-native style while
> > also
> > >>>>> fixing the mock order issue.
> > >>>>>
> > >>>>> "Sure! Since you asked ..." sounds like an AI bot.
> > >>>>>
> > >>>>>> That got me thinking — what do you think about adding a guideline
> > >>>>> document
> > >>>>> for writing tests, similar to how we have a coding style guide?
> > >>>>>
> > >>>>> Absolutely  - we already have some "seed' of it "Writing tests"
> > >>> chapter in
> > >>>>> contributing guideline, but we could definitely make it more
> > detailed.
> > >>>>>
> > >>>>>
> > >>>>>
> > >>>
> >
> https://github.com/apache/airflow/blob/main/contributing-docs/testing/unit_tests.rst#writing-unit-tests
> > >>>>>
> > >>>>> And - speaking of AI - this is becoming more and more important to
> > >>> describe
> > >>>>> any common rules we have and context - so that using Agentic AI
> > yields
> > >>>>> better results. Kaxil already added
> > >>>>> https://github.com/apache/airflow/blob/main/AGENTS.md which
> > describes
> > >>>>> context for coding agents lile Codex - and we could improve it and
> > link
> > >>>>> more docs from our repo if they get more of our agreed
> "conventions"
> > -
> > >>> then
> > >>>>> Agents would get it as context and their generated code would be
> > >>> consistent
> > >>>>> with what we describe there.
> > >>>>>
> > >>>>> In a way - I think having a good documentation on processes, tools
> > and
> > >>>>> conventions was always something I've been after, but with the
> > Agentic
> > >>>>> workflows it might significantly boost the quality of generated
> code
> > >>> if we
> > >>>>> have more of those conventions and guidelines described.
> > >>>>>
> > >>>>> So .... ABSOLUTELY ... the more we describe in there, the better.
> And
> > >>> we
> > >>>>> have no more excuse that "anyhow no-one reads it" - because the
> > coding
> > >>>>> agents WILL be reading it and acting accordingly. So I think this
> is
> > a
> > >>> very
> > >>>>> good investment to make.
> > >>>>>
> > >>>>> J.
> > >>>>>
> > >>>>>
> > >>>>>
> > >>>>>
> > >>>>>
> > >>>>>> On Sat, Jul 5, 2025 at 2:07 PM Kyungjun Lee <
> > kyungjunlee...@gmail.com
> > >>>>
> > >>>>>> wrote:
> > >>>>>>
> > >>>>>> Haha ... I'm curious — which part sounded like ChatGPT style?
> > >>>>>> English isn't my first language, so I did get a little help from
> it.
> > >>>>>>
> > >>>>>> But thank you — I actually learned something new from your
> comment!
> > >>>>>> That got me thinking — what do you think about adding a guideline
> > >>>>> document
> > >>>>>> for writing tests, similar to how we have a coding style guide? It
> > >>> might
> > >>>>>> help ensure consistency across the Airflow codebase when it comes
> to
> > >>>>>> testing styles as well.
> > >>>>>>
> > >>>>>> 2025년 7월 5일 (토) 오후 8:52, Jarek Potiuk <ja...@potiuk.com>님이 작성:
> > >>>>>>
> > >>>>>>> But of course - i'd love to hear what others think - it's not a
> > "very
> > >>>>>>> strong" opinion.
> > >>>>>>>
> > >>>>>>> On Sat, Jul 5, 2025 at 1:48 PM Jarek Potiuk <ja...@potiuk.com>
> > >>> wrote:
> > >>>>>>>
> > >>>>>>>> Cool. That's what I wanted to see.
> > >>>>>>>>
> > >>>>>>>> By the way - not that there's anything wrong - but was the
> answer
> > >>>>>> written
> > >>>>>>>> by AI initially ? The first paragraph looks suspiciously like
> Chat
> > >>>>> GPT
> > >>>>>>>> answer :D ?
> > >>>>>>>>
> > >>>>>>>> Comment from my side: I personally prefer the original style.
> It's
> > >>>>> more
> > >>>>>>>> concise and it is easier to read - you see as if the call was
> > >>>>> actually
> > >>>>>>>> written down. Also this is quite a bit too many assertions in
> the
> > >>>>>> second
> > >>>>>>>> case and it takes a lot of mental effort to understand what
> > actually
> > >>>>> is
> > >>>>>>>> being asserted.
> > >>>>>>>>
> > >>>>>>>> There is a "school" of writing unit tests that every test should
> > >>> have
> > >>>>>> ONE
> > >>>>>>>> assertion only. Always. I think it is a bit extreme, and I do
> not
> > >>>>>> follow
> > >>>>>>> it
> > >>>>>>>> myself but I think it is also a kind of good direction to have
> ->
> > >>> the
> > >>>>>>> fewer
> > >>>>>>>> assertions you have in your test, the better (I think).
> > >>>>>>>>
> > >>>>>>>> I think tests should be mostly optimized for easiness of reading
> > and
> > >>>>>>>> understanding what is being tested - and it's just not that easy
> > in
> > >>>>> the
> > >>>>>>>> second case.
> > >>>>>>>>
> > >>>>>>>> J.
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>> On Sat, Jul 5, 2025 at 1:39 PM Kyungjun Lee <
> > >>>>> kyungjunlee...@gmail.com>
> > >>>>>>>> wrote:
> > >>>>>>>>
> > >>>>>>>>> Sure! Since you asked for how the test *should* be written, I
> > took
> > >>>>> the
> > >>>>>>>>> opportunity to clean it up using a more pytest-native style
> while
> > >>>>> also
> > >>>>>>>>> fixing the mock order issue.
> > >>>>>>>>>
> > >>>>>>>>> Here’s the updated test:
> > >>>>>>>>>
> > >>>>>>>>> ```python
> > >>>>>>>>>
> > >>>>>>>>> @pytest.mark.parametrize(
> > >>>>>>>>>   argnames="conn_id, account_id",
> > >>>>>>>>>   argvalues=[(ACCOUNT_ID_CONN, None), (NO_ACCOUNT_ID_CONN,
> > >>>>>>> ACCOUNT_ID)],
> > >>>>>>>>>   ids=["default_account", "explicit_account"],
> > >>>>>>>>> )
> > >>>>>>>>> @patch.object(DbtCloudHook, "run")
> > >>>>>>>>> @patch.object(DbtCloudHook, "_paginate")
> > >>>>>>>>> def test_get_account(self, mock_paginate, mock_http_run,
> conn_id,
> > >>>>>>>>> account_id):
> > >>>>>>>>>   hook = DbtCloudHook(conn_id)
> > >>>>>>>>>   hook.get_account(account_id=account_id)
> > >>>>>>>>>
> > >>>>>>>>>   assert hook.method == "GET"
> > >>>>>>>>>
> > >>>>>>>>>   expected_account_id = account_id or DEFAULT_ACCOUNT_ID
> > >>>>>>>>>
> > >>>>>>>>>   assert mock_http_run.call_count == 1
> > >>>>>>>>>   assert mock_http_run.call_args.args == ()
> > >>>>>>>>>   assert mock_http_run.call_args.kwargs == {
> > >>>>>>>>>       "endpoint": f"api/v2/accounts/{expected_account_id}/",
> > >>>>>>>>>       "data": None,
> > >>>>>>>>>       "extra_options": None,
> > >>>>>>>>>   }
> > >>>>>>>>>
> > >>>>>>>>>   assert mock_paginate.call_count == 0
> > >>>>>>>>>
> > >>>>>>>>> ```
> > >>>>>>>>> Why I chose this style:
> > >>>>>>>>>
> > >>>>>>>>>  -
> > >>>>>>>>>
> > >>>>>>>>>  *Mock verification using assert*: Instead of
> > >>>>>>>>>  mock.assert_called_once_with(...), I used call_count and
> > >>>>> call_args.
> > >>>>>>>>> This
> > >>>>>>>>>  approach aligns better with pytest’s idioms and produces
> > cleaner,
> > >>>>>>> more
> > >>>>>>>>>  readable error messages when assertions fail.
> > >>>>>>>>>  -
> > >>>>>>>>>
> > >>>>>>>>>  *Explicit verification*: Using call_args.args and
> > >>>>> call_args.kwargs
> > >>>>>>>>> makes
> > >>>>>>>>>  the test behavior very explicit, which helps with debugging
> and
> > >>>>>>>>>  understanding the exact calls made.
> > >>>>>>>>>  -
> > >>>>>>>>>
> > >>>>>>>>>  *Decorator order matching argument order*: As @patch
> decorators
> > >>>>>> apply
> > >>>>>>>>>  from the bottom up, the argument order has been corrected to
> > >>>>> match
> > >>>>>> (
> > >>>>>>>>>  mock_paginate first, then mock_http_run).
> > >>>>>>>>>
> > >>>>>>>>> Let me know if you'd like to follow a slightly different
> > convention
> > >>>>> —
> > >>>>>>>>> happy
> > >>>>>>>>> to adjust!
> > >>>>>>>>>
> > >>>>>>>>> I was lucky to have the chance to explain this while fixing a
> > >>>>> related
> > >>>>>>> bug.
> > >>>>>>>>> You can refer to the changes in this PR:
> > >>>>>>>>> https://github.com/apache/airflow/pull/52905
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>> 2025년 7월 5일 (토) 오후 8:09, Jarek Potiuk <ja...@potiuk.com>님이 작성:
> > >>>>>>>>>
> > >>>>>>>>>> Just post how you think the test should be written :)
> > >>>>>>>>>>
> > >>>>>>>>>> On Sat, Jul 5, 2025 at 1:08 PM Jarek Potiuk <ja...@potiuk.com
> >
> > >>>>>> wrote:
> > >>>>>>>>>>
> > >>>>>>>>>>> I already mentioned it in slack - but how would you propose
> to
> > >>>>>>> rewrite
> > >>>>>>>>>> the
> > >>>>>>>>>>> "mixed" case to be more consistent ?
> > >>>>>>>>>>>
> > >>>>>>>>>>> On Sat, Jul 5, 2025 at 12:47 PM Kyungjun Lee <
> > >>>>>>>>> kyungjunlee...@gmail.com>
> > >>>>>>>>>>> wrote:
> > >>>>>>>>>>>
> > >>>>>>>>>>>> Hi all,
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> While reviewing and contributing to Airflow tests, I’ve
> > noticed
> > >>>>>> an
> > >>>>>>>>>>>> inconsistency in how assertions are written. Some tests use
> > >>>>>>>>>>>> `unittest`-style assertions like
> > >>>>> `mock.assert_called_once_with`,
> > >>>>>>>>> while
> > >>>>>>>>>>>> others use plain `assert` statements in the `pytest` style.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Here's an example of a test using the mixed style:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> ```python
> > >>>>>>>>>>>> @pytest.mark.parametrize(
> > >>>>>>>>>>>>   argnames="conn_id, account_id",
> > >>>>>>>>>>>>   argvalues=[(ACCOUNT_ID_CONN, None), (NO_ACCOUNT_ID_CONN,
> > >>>>>>>>>> ACCOUNT_ID)],
> > >>>>>>>>>>>>   ids=["default_account", "explicit_account"],
> > >>>>>>>>>>>> )
> > >>>>>>>>>>>> @patch.object(DbtCloudHook, "run")
> > >>>>>>>>>>>> @patch.object(DbtCloudHook, "_paginate")
> > >>>>>>>>>>>> def test_get_account(self, mock_http_run, mock_paginate,
> > >>>>> conn_id,
> > >>>>>>>>>>>> account_id):
> > >>>>>>>>>>>>   hook = DbtCloudHook(conn_id)
> > >>>>>>>>>>>>   hook.get_account(account_id=account_id)
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   assert hook.method == "GET"
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   _account_id = account_id or DEFAULT_ACCOUNT_ID
> > >>>>>>>>>>>>   hook.run.assert_called_once_with(
> > >>>>>>>>>>>>       endpoint=f"api/v2/accounts/{_account_id}/", data=None,
> > >>>>>>>>>>>> extra_options=None
> > >>>>>>>>>>>>   )
> > >>>>>>>>>>>>   hook._paginate.assert_not_called()
> > >>>>>>>>>>>> ```
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> In IDEs and type-checkers (like PyCharm or MyPy), this
> > >>>>> sometimes
> > >>>>>>>>> causes
> > >>>>>>>>>>>> weak warnings
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> ```
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Cannot find reference 'assert_called_once_with' in
> 'function'
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> ```
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> This could confuse newcomers or contributors unfamiliar with
> > >>>>>>> mocking
> > >>>>>>>>>>>> behavior or type limitations in dynamic typing.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> To improve clarity and accessibility for
> > >>>>> contributors—especially
> > >>>>>>>>> those
> > >>>>>>>>>> new
> > >>>>>>>>>>>> to the project—I’d like to propose *moving toward consistent
> > >>>>> use
> > >>>>>> of
> > >>>>>>>>>> plain
> > >>>>>>>>>>>> assert statements* for test validations wherever possible.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> *Proposed Benefits*:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>  -
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>  Easier onboarding for first-time contributors
> > >>>>>>>>>>>>  -
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>  Better IDE support and fewer confusing warnings
> > >>>>>>>>>>>>  -
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>  More consistent and readable test style across the project
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> I'd love to hear your thoughts on whether this direction
> makes
> > >>>>>>> sense
> > >>>>>>>>> for
> > >>>>>>>>>>>> the project. If agreed, I’d also be happy to help align
> > >>>>> existing
> > >>>>>>>>> tests
> > >>>>>>>>>>>> gradually.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Thanks!
> > >>>>>>>>>>>> Kyungjun Lee
> > >>>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>
> > >>>>>>
> > >>>>>
> > >>>
> > >>>
> > >>> ---------------------------------------------------------------------
> > >>> To unsubscribe, e-mail: dev-unsubscr...@airflow.apache.org
> > >>> For additional commands, e-mail: dev-h...@airflow.apache.org
> > >>>
> > >>>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscr...@airflow.apache.org
> > For additional commands, e-mail: dev-h...@airflow.apache.org
> >
> >
>

Reply via email to