Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve healthcheck message when @given() wraps an async def function (which returns a coroutine object) #3054

Closed
MapleCCC opened this issue Aug 12, 2021 · 4 comments
Labels
legibility make errors helpful and Hypothesis grokable

Comments

@MapleCCC
Copy link
Contributor

The document states that besides running the test with pytest discovery, "we could also have run it explicitly ourselves". This is true for regular hypothesis-decorated tests. But it's not true for hypothesis-decorated coroutine tests.

import asyncio
import pytest
from hypothesis import given
from hypothesis.strategies import integers

def inc(x: int) -> int:
    return x + 1

@given(integers())
def test1(i: int) -> None:
    assert inc(i) == i + 1

@given(integers())
@pytest.mark.asyncio
async def test2(i: int) -> None:
    await asyncio.sleep(0.001)
    assert inc(i) == i + 1

Running these tests with pytest is fine. But if we run them explicitly,

if __name__ == "__main__":
    test1()
    test2()

test1() runs fine, but test2() yields hypothesis.errors.FailedHealthCheck: Tests run under @given should return None, but test2 returned <coroutine object test2 at 0x000001972E473F40> instead.

Should we consider this a bug? Because this directly contradicts the instructions from the document.

@Zac-HD
Copy link
Member

Zac-HD commented Aug 13, 2021

Hypothesis doesn't actually support async def coroutine functions; it's just that pytest-asyncio transparently handles that for you using our hook to insert an async-to-sync wrapper.

We could use a more specific error message for coroutine objects though.

@Zac-HD Zac-HD added the legibility make errors helpful and Hypothesis grokable label Aug 13, 2021
@Zac-HD Zac-HD changed the title Explicitly running coroutine tests doesn't succeed Improve healthcheck message when @given() wraps an async def function (which returns a coroutine object) Aug 13, 2021
@MapleCCC
Copy link
Contributor Author

@Zac-HD Thank you for your kind help and informative reply. I understand what happened now.

Another problem is that the type checker I used, Pyright, detects a type error in the above code I presented.

The type annotation of @pytest.mark.asyncio is MarkDecorator, which basically is an identity function in the eyes of type checker, and just left the type annotation of its decorated function intact. From the source code, the type annotation of @given() is Callable[[Callable[..., None]], Callable[..., None]], and it's not compatible with an async function as input. Hence the type error.

Do you have any advice in how to fix this type error? Anything that we can do in hypothesis or pytest-asyncio? Or maybe we should just use # type: ignore to disable type checking for this specific use case?

@Zac-HD
Copy link
Member

Zac-HD commented Aug 13, 2021

You'll need a # type: ignore somewhere, but I'd probably put it into a shim that replaces the @pytest.mark.asyncio decorator:

def mark_asyncio(f: Coroutine[None, None, None]) -> Callable[..., None]:
    # The actual replacement is handled by magic inside pytest-asyncio
    # which understands Hypothesis, so we just ignore the types here.
    return pytest.mark.asyncio(f)  # type: ignore

@given(integers())
@mark_asyncio
async def test2(i: int) -> None:
    await asyncio.sleep(0.001)
    assert inc(i) == i + 1

@MapleCCC
Copy link
Contributor Author

@Zac-HD Thank you for your kind help. I tried your suggested workaround, and it worked perfectly. That's a very creative solution.

halstead pushed a commit to openembedded/openembedded-core that referenced this issue Aug 22, 2021
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
kraj pushed a commit to YoeDistro/poky-old that referenced this issue Aug 22, 2021
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

(From OE-Core rev: 616f4ce10d4e09eaa89755e87e607011dc67441b)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
jpuhlman pushed a commit to MontaVista-OpenSourceTechnology/poky that referenced this issue Aug 22, 2021
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

(From OE-Core rev: 616f4ce10d4e09eaa89755e87e607011dc67441b)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
halstead pushed a commit to openembedded/openembedded-core that referenced this issue Aug 22, 2021
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
daregit pushed a commit to daregit/yocto-combined that referenced this issue May 22, 2024
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

(From OE-Core rev: ca0039a6e5524ab1e74df285ce16460dc980da65)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
daregit pushed a commit to daregit/yocto-combined that referenced this issue May 22, 2024
6.15.0 - 2021-08-22

This release emits a more useful error message when @given() is applied to
a coroutine function, i.e. one defined using async def (issue #3054).

This was previously only handled by the generic return_value health check,
which doesn’t direct you to use either a custom executor or a library such
as pytest-trio or pytest-asyncio to handle it for you.

6.14.9 - 2021-08-20

This patch fixes a regression in Hypothesis 6.14.8, where from_type() failed
to resolve types which inherit from multiple parametrised generic types,
affecting the returns package (issue #3060).

References:
HypothesisWorks/hypothesis#3054
HypothesisWorks/hypothesis#3060

(From OE-Core rev: ca0039a6e5524ab1e74df285ce16460dc980da65)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legibility make errors helpful and Hypothesis grokable
Projects
None yet
Development

No branches or pull requests

2 participants