由于地址冲突,Django的LiveServerTestCase总是失败...尽管地址显得空闲

时间:2013-12-16 20:03:18

标签: python django

我正在努力清理我的Django功能测试以使用LiveServerTestCase,而不是在背景中运行的开发环境的实例上反弹基于selenium的测试,而且我已经碰壁了。每次我尝试运行LiveServerTestCase测试时,都会收到以下错误:

======================================================================
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

非常有趣,考虑sudo netstat -netp | grep 8081没有产生任何结果。一些背景:我正在使用Django 1.6,我使用鼻子,django-nose,鼻子排除,但我已经有效地将它们切掉以帮助诊断问题。我正在使用的代码非常简单:

from django.test import LiveServerTestCase
class TestCmsLogin(LiveServerTestCase):
    def test_a_test_itself(self):
        self.assertTrue(True)

我找不到关于这个主题的任何现有技术,而且Djangoproject的bug追踪器很干净。我错过了什么?

编辑:今天早上这个问题是不可复制的,无论是标记端口8081,因为打开不再导致问题。

edit2:在我的写作中将8081误导为8082,修复(并检查以确保我当时正确)。

5 个答案:

答案 0 :(得分:13)

在前一个测试生成内部服务器错误之后运行后续测试时,这开始发生在我身上。在Mac上,使用lsof使用端口查找程序,并将其终止。 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

答案 1 :(得分:13)

您可以设置(在settings.py中)环境变量DJANGO_LIVE_TEST_SERVER_ADDRESS以包含将尝试的多个端口范围:

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

我自己也有同样的问题,也许这可以帮助别人。

答案 2 :(得分:2)

如果未设置环境变量DJANGO_LIVE_TEST_SERVER_ADDRESS,则启动实时测试服务器的默认地址为localhost:8081。请参阅LiveServerTestCase src代码。

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

由于操作系统似乎在抱怨端口8081正在使用中。通过运行如下测试,可以快速选择另一个端口(比如9000)。

/manage.py test functional_tests --liveserver :9000

但是,明确设置DJANGO_LIVE_TEST_SERVER_ADDRESS是理想的。

export DJANGO_LIVE_TEST_SERVER_ADDRESS="localhost:9000"

答案 3 :(得分:0)

如果您要将测试用例分开,请更改您的拆解方法

在一个文件中测试可以使用.close()方法

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

在多个文件中进行测试需要启动新线程。

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

答案 4 :(得分:0)

对于它的价值,我遇到了类似的问题,并以稍微不同的方式解决了它。我们的LiveServerTestCase在虚拟化环境中与其他几台机器一起运行,并且需要保持相同的端口,以便Nginx(在另一台机器上)能够正确地重定向流量。

问题所在的行是https://github.com/django/django/blob/1.11.15/django/test/testcases.py#L1296,特别是allow_reuse_address=False

allow_reuse_address的默认值为True,在此被覆盖,期望服务器线程将绑定到端口0,并保证有一个空闲端口。但是,如果端口在后续运行之间被重用,则在下一次测试启动时,操作系统尚未使上一个测试的套接字请求超时。提供更多详细信息,here

我的解决方案只是继承并覆盖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):
        # ...

请注意,这是针对django v1.11的。在更高的版本中,名称略有更改(我认为从WSGIServer更改为ThreadedWSGIServer)。

相关问题