Django's LiveServerTestCase Always Fails Due to Conflicting Address… Despite Address Appearing Free

前端 未结 5 1075
心在旅途
心在旅途 2020-12-31 05:45

I\'m currently working on cleaning my Django functional tests to use the LiveServerTestCase rather than bouncing selenium based tests off an instance of the development envi

相关标签:
5条回答
  • 2020-12-31 06:10

    This started happening to me when running subsequent tests after a previous one generated an internal server error. On a mac, use lsof to find the program using the port, and kill it. E.g.:

    $ sudo lsof -i :8081
    COMMAND    PID    USER   FD   TYPE            DEVICE SIZE/OFF NODE NAME
    firefox-b 1097 username    3u  IPv4 0x94495559c6dea35      0t0  TCP localhost:sunproxyadmin (LISTEN)
    
    $ kill -9 1097
    
    0 讨论(0)
  • 2020-12-31 06:10

    Change your teardown method if you're going to separate your test cases

    Testing in one file is okay to use the .close() method

    def tearDown(self):
        self.browser.close()
    

    Testing in multiple files will require starting new threads.

    def tearDown(self):
        self.browser.quit()
    
    0 讨论(0)
  • 2020-12-31 06:12

    If environment variable DJANGO_LIVE_TEST_SERVER_ADDRESS is not set the default address to start the live test server is localhost:8081. See LiveServerTestCase src code.

      # Launch the live server's thread
        specified_address = os.environ.get(
            'DJANGO_LIVE_TEST_SERVER_ADDRESS', 'localhost:8081')
    

    As the OS seems to be complaining about the port 8081 being in use. One can quickly pick another port (say 9000) by running the tests like below.

    /manage.py test functional_tests --liveserver :9000
    

    However, explicitly setting the DJANGO_LIVE_TEST_SERVER_ADDRESS would be ideal.

    export DJANGO_LIVE_TEST_SERVER_ADDRESS="localhost:9000"
    
    0 讨论(0)
  • 2020-12-31 06:25

    For what it's worth, I had a similar issue and solved it slightly differently. Our LiveServerTestCase was running alongside a few other machines in a virtualized environment, and needed to keep the same port so Nginx (on a different machine) would be able to redirect traffic properly.

    The problematic line was https://github.com/django/django/blob/1.11.15/django/test/testcases.py#L1296, specifically allow_reuse_address=False.

    allow_reuse_address defaults to True, and is overridden here with the expectation that the server thread will bind to port 0, and will be guaranteed to have a free port. If the port is reused between subsequent runs, though, when the next test starts the OS hasn't timed out the previous test's socket request yet. More details are available here

    My solution was just to subclass and override the kwarg:

    import django.test.testcases
    from django.core.servers.basehttp import WSGIServer
    
    
    class LiveServerThreadWithReuse(django.test.testcases.LiveServerThread):
        """
        This miniclass overrides _create_server to allow port reuse. This avoids creating
        "address already in use" errors for tests that have been run subsequently.
        """
    
        def _create_server(self):
            return WSGIServer(
                (self.host, self.port),
                django.test.testcases.QuietWSGIRequestHandler,
                allow_reuse_address=True,
            )
    
    
    class MyFunctionalTestCase(django.test.testcases.LiveServerTestCase):
        port = 8000
        server_thread_class = LiveServerThreadWithReuse
    
        def test_something(self):
            # ...
    

    Note that this was for django v1.11. In later versions, the names have slightly changed (I think from WSGIServer to ThreadedWSGIServer).

    0 讨论(0)
  • 2020-12-31 06:31

    You can set (in settings.py) the environment variable DJANGO_LIVE_TEST_SERVER_ADDRESS to include multiple ranges of ports that will be attempted:

    os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS']="localhost:8000-8010,8080,9200-9300"
    

    Had the same issue myself, maybe this helps someone out.

    0 讨论(0)
提交回复
热议问题