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

Making tests with AioHTTPTestCase #2032

Closed
cecton opened this issue Jun 28, 2017 · 3 comments
Closed

Making tests with AioHTTPTestCase #2032

cecton opened this issue Jun 28, 2017 · 3 comments
Labels

Comments

@cecton
Copy link
Contributor

cecton commented Jun 28, 2017

Long story short

I'm trying to make my test to run on the same port instead of a random port. The reason is that I'm making integration tests and I need it to receive calls from another service that I can't really configure the port easily.

My idea is that I need to make a class FixedPortTestServer that will inherit from TestServer and override the start_server method to force a specific port.

Then I need to pass this instance to the TestClient initialization. The AioHTTPTestCase use the result of get_application and give it to TestClient init parameters. This makes me think that I can make get_application return the FixedPortTestServer instance instead of the application instance:

    async def get_application(self):
        return FixedPortTestServer(my_app)

Which is wrong... Now I have a properly initialized TestClient using my TestServer but self.app in the AioHTTPTestCase give me the TestServer instead of my application which doesn't make any sense.

Expected behaviour

I expect to get the application from self.app within a test method of AioHTTPTestCase and I want to be able to override the TestServer instance with whatever BaseTestServer instance I want without needing to override a private method.

Actual behaviour

Currently, my only way to override the TestServer instance in the initialization of the TestClient is to override the private method _get_client in the AioHTTPTestCase.

Steps to reproduce

import asyncio
import socket
from aiohttp.helpers import sentinel
from aiohttp.test_utils import AioHTTPTestCase, TestServer, unittest_run_loop
from yarl import URL

from mymodule import myapp


class FixedPortTestServer(TestServer):
    @asyncio.coroutine
    def start_server(self, loop=None, **kwargs):
        if self.server:
            return
        self._loop = loop
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.bind((self.host, 8080)) # force port
        self.port = self._socket.getsockname()[1]
        self._ssl = kwargs.pop('ssl', None)
        if self.scheme is sentinel:
            if self._ssl:
                scheme = 'https'
            else:
                scheme = 'http'
            self.scheme = 'http'
        self._root = URL('{}:https://{}:{}'.format(self.scheme,
                                             self.host,
                                             self.port))

        handler = yield from self._make_factory(**kwargs)
        self.server = yield from self._loop.create_server(
            handler, ssl=self._ssl, sock=self._socket)


class MyTestCase(AioHTTPTestCase):
    async def get_application(self):
        return FixedPortTestServer(myapp)

    @unittest_run_loop
    async def test_initialization(self):
        self.assertIs(self.app, myapp)

Your environment

Python 3.6

@cecton
Copy link
Contributor Author

cecton commented Jun 28, 2017

I believe the whole confusion come from the flexible parameter app_or_server. This is a typical problem in Python because we can use any instance of anything we want anywhere.

If you use an Application instance, then self.app will point to the application. But if you use a BaseTestServer instance then self.app is that instance.

In my opinion the type of self.app should not change. It is an application and that's all it is. Therefore I would suggest to make a new overridable method get_test_server that will, by default, instantiate the default TestServer using the application returned by get_application.

@asvetlov
Copy link
Member

asvetlov commented Jul 25, 2017

Fixed by #2074

@lock
Copy link

lock bot commented Oct 28, 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 28, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 28, 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