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

How to test aiohttp.web applications #715

Closed
farefernandez opened this issue Dec 30, 2015 · 8 comments
Closed

How to test aiohttp.web applications #715

farefernandez opened this issue Dec 30, 2015 · 8 comments
Labels

Comments

@farefernandez
Copy link

Hi,

I'm trying to unit-test a simple app I'm creating. Basically, given this code:

async def hello(request):
    return web.Response(body=b"Hello, world")

I'd like to simulate a request to the hello function and verify that the response code is 200. I used to do similar things with the Django teat st client but I'm not sure how to do the same thing with aiohttp.web.

I had a look at webtest-aiohttp but I couldn't get it working with recent versions of aiohttp.web.

Thanks!

@asvetlov
Copy link
Member

@farefernandez
Copy link
Author

Hi Andrew,

I was able to write a test and it works great, thanks for the pointer. My understanding is that being able to test is largely dependant on conftest.py setting up the correct environment.

I made a few changes to conftest.py to adapt it to my situation. In your original version, app and request handlers are created on the fly by the testcases, whereas in my case I'm testing an existing app with its own request handlers.

To do so, I changed the loop fixture creator to pick up the event loop from the one I declared in my application:

@pytest.yield_fixture
def loop(request):
    from .app import loop
    yield loop

and I did the same thing for create_server, to pick up the app from the one I declared instead of creating a new one:

@pytest.yield_fixture
def create_server(loop, unused_port):
    app = handler = srv = None

    @asyncio.coroutine
    def create(*, debug=False, ssl_ctx=None, proto='http'):
        nonlocal app, handler, srv
        from .app import app ####  <--------- THIS CHANGED --------------
        port = unused_port()
        handler = app.make_handler(debug=debug, keep_alive_on=False)
        srv = yield from loop.create_server(handler, '127.0.0.1', port,
                                            ssl=ssl_ctx)
        if ssl_ctx:
            proto += 's'
        url = "{}://127.0.0.1:{}".format(proto, port)
        return app, url

    yield create

    @asyncio.coroutine
    def finish():
        yield from handler.finish_connections()
        yield from app.finish()
        srv.close()
        yield from srv.wait_closed()

    loop.run_until_complete(finish())

After this, I was able to run a test with:

@pytest.mark.run_loop
async def test_hello(create_app_and_client):
    app, client = await create_app_and_client()
    async with client.get('/') as resp:
        assert resp.status == 200

Do you think I'm doing the right thing? While It certainly seems like working, I'm really not sure that this is correct.

Thanks!

@asvetlov
Copy link
Member

I hate global variables like app and loop from your code.
It makes testing awful due lack of test isolation.
But if it floats your boat you may live with global vars.

P.S. Don't close app yield from app.finish() on every test if you use app singleton.

@farefernandez
Copy link
Author

Thanks Andrew,

I have refactored the app to avoid global variables and I'm using the conftest.py code as it is to test my app.

May I suggest that a chapter about testing would be a very helpful documentation addition.

Thanks!

@asvetlov
Copy link
Member

asvetlov commented Jan 1, 2016

I really want to have a good chapter about writing tests for aiohttp based projects.
Would you start with PR?
I'll help you, sure -- but we need a starting point for the task.
Also I need a feedback from casual aiohttp users: I'm aiohttp developer and maybe my experience has lack of requests from newbies.
I have strong feeling that some obvious things from my perspective should be explained and accentuated.

@farefernandez
Copy link
Author

Hi Andrew,

I resumed work on my project based aiohttp.web and unfortunately I don't really feel enough qualified to even start a PR about testing with aiohttp.web. I'm still trying to wrap my head around the conftest.py shipped with aiohttp, but it really requires some deep understanding of both py.test and aiohttp/asyncio which, for the time being, I don't have (It's my first project with both libraries). I'm sorry I'm not able to contribute for now, but as you well say, I'm a casual user. And I can tell you that testing is being hard for me :-)

@asvetlov
Copy link
Member

asvetlov commented Mar 4, 2016

I'll publish a testing support in next aiohttp release.

@lock
Copy link

lock bot commented Oct 29, 2019

This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.

If you feel like there's important points made in this discussion,
please include those exceprts into that new issue.

@lock lock bot added the outdated label Oct 29, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants