Skip to content

Using async libraries with PyTest #3809

Closed
@amit-traiana

Description

@amit-traiana

Hello everyone!

I am experiencing inconsistent behaviour when using async/sync fixtures. Our tests using pyppeteer (Python wrapper around Google's Puppeteer library). Almost all pyppeteer methods are async. A common code will look like so:

from pyppeteer import launch

browser = await launch()
page = await browser.newPage()
await page.goto('http://example.com')
await page.screenshot({'path': 'example.png'})
await browser.close()

So in order to be able to run async tests, I'm using pytest-asyncio (and there actually an integration bug between pytest-asyncio and pyppeteer. A bug was opened on the pytest-asyncio that explains the issue). The above share a common code that should get executed before every test:

browser = await launch()
page = await browser.newPage()

and at the end of each test:

await browser.close()

So obviously, a fixture is needed here.

@pytest.fixture()
async def page():
    browser = await launch()
    page = await browser.newPage()
    yield page
    await browser.close()

The above will work properly if using a normal fixture (like seen in the sftp client example on the official documentation), and while it's a bit confusing yield returns a value and not an iterator - there no problem with using the fixture. But unlike yield in a non-async fixture, the yield here will not return the value of page, but instead will return an async-generator. So the following test will fail:

@pytest.mark.asyncio
async def test_some_test(page)
    await page.goto('http://example.com')

with the following error: AttributeError: 'async_generator' object has no attribute 'goto'. The only way around it is to manually iterate over async generator so the test will look like so:

@pytest.mark.asyncio
async def test_some_test(page)
    async for x in page:
        await page.goto('http://example.com')

It that the right way of doing it? because it seems a bit cumbersome and contradict how yield works on non-async methods.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions