Git Product home page Git Product logo

Comments (9)

and-semakin avatar and-semakin commented on July 23, 2024 12

I'll just put links here for future strangers.

Also awesome explanation about the async test client: https://fastapi.tiangolo.com/advanced/async-tests/ (it's about FastAPI but it still should be applicable to pure Starlette).

My example of async test client fixture:

# conftest.py
from asgi_lifespan import LifespanManager
from httpx import AsyncClient


@pytest.fixture()
async def client() -> Iterator[AsyncClient]:
    async with LifespanManager(app):
        async with AsyncClient(app=app, base_url="http://test") as ac:
            yield ac


# test_app.py
@pytest.mark.asyncio
async def test_endpoint(client: AsyncClient) -> None:
    response = await client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Tomato"}

from starlette.

ryankask avatar ryankask commented on July 23, 2024 5

@mackeyja92 Here's a gist: https://gist.github.com/ryankask/90c0dc155d3f95a52a1eaa0ac4ef63d0.

I needed to make it async all the way down to this call loop.run_until_complete(connection(receive, send)) deep in the adapter so a nested loop wasn't started.

To do this, I combined the ASGI adapter Tom wrote with requests' Session API. I removed some of the Session-related code that I didn't think was relevant but I may have removed or left in too much.

I use pytest with pytest-asyncio doing something like this

@pytest.fixture
def client():
    return StarletteTestClient(starlette_app)

@pytest.mark.asyncio
async def test_update_company(client):
    company = await CompanyStore.create(name="Great Software")
    data = {
        "name": "Awesome Software",
    }

    response = await client.patch(f"/companies/{company.id}", json=data)

    assert response.status_code == 200
    updated_company = await CompanyStore.get(company.id)
    assert updated_company.name == "Awesome Software"

All my app code is async so to test in same way I've always done (arrange, act, assert, this time asynchronously), I think I need an async test client. This way pytest-asyncio can manage the loop and I can use pytest naturally. Maybe I need to just change the way I test so hopefully someone points out a better way.

I thought it would be better to use aiohttp's equivalent of a requests' adapter but I didn't spend much time figuring it out.

from starlette.

euri10 avatar euri10 commented on July 23, 2024 3

For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.

you can also use httpx and the asgi-lifespan by @florimondmanca !

from starlette.

tomchristie avatar tomchristie commented on July 23, 2024

Okay, so...

The "lifespan" events are useful here. See https://www.starlette.io/events/

One option would be for you to add the setup teardown events to the app when in test mode, and then use with LifespanContext(app) in the test cases.

Alternatively if you don't want to register the events on the app itself you can use just the lifespan handler by itself, so...

lifespan = LifespanHandler()

# We should probably add a regular function-based interface too. `lifespan.add_event_handler('startup', func)
@lifespan.on_event('startup')  
async def startup():
    ...

@lifespan.on_event('cleanup')  
async def cleanup():
    ...

You're then able to use something like this in your test cases:

with LifetimeContext(lifetime):
    ...

It's a regular sync interface at that point, but it'll marshall bridging to the async calls for you.
It'd be interesting if we could look at how those would correspond to pytest fixtures.

from starlette.

tomchristie avatar tomchristie commented on July 23, 2024

Also, we may want to reorganise the docs here, so that LifespanContext gets included in the test section.

from starlette.

ryankask avatar ryankask commented on July 23, 2024

Thanks for the tips. I can see how it's possible to use these features along with Starlette's test client.

Since I'm already using pytest-asyncio to test other parts of the app, I'm going to continue using the async test client to keep things consistent.

I'll close this issue since you've answered the original question.

from starlette.

jared-mackey avatar jared-mackey commented on July 23, 2024

@ryankask Would you be willing to setup a package for your async test client code? I'd love to take a look and see if we could use it as well.

from starlette.

gjeusel avatar gjeusel commented on July 23, 2024

For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.

from starlette.

gjeusel avatar gjeusel commented on July 23, 2024

For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.

you can also use httpx and the asgi-lifespan by @florimondmanca !

httpx is much better ! Thx

from starlette.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.