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 environment running in the background, and I've hit a wall. Every time I try to run a LiveServerTestCase test, I get the following error:
======================================================================
ERROR: setUpClass (fun_tests.tests.backend.TestCmsLogin)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/user/Documents/env/local/lib/python2.7/site-packages/django/test/testcases.py", line 1187, in setUpClass
raise cls.server_thread.error
error: [Errno 98] Address already in use
Super fun, considering sudo netstat -netp | grep 8081
yields nothing. Some background: I'm using Django 1.6, and I was using nose, django-nose, nose-exclude, but I've effectively chopped them out to help diagnose the issue. The code I'm using is abysmally simple:
from django.test import LiveServerTestCase
class TestCmsLogin(LiveServerTestCase):
def test_a_test_itself(self):
self.assertTrue(True)
I can't find any prior art on the subject, and Djangoproject's bug tracker is clean. What am I missing?
Edit: This morning the issue is irreproducible, whatever was flagging port 8081 as open is no longer causing issues.
edit2: Mistyped 8081 as 8082 in my writeup, fixed (and checked to make sure I had it right at the time).
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.
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
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"
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
).
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With