【问题标题】:Django's LiveServerTestCase Always Fails Due to Conflicting Address... Despite Address Appearing Free由于地址冲突,Django 的 LiveServerTestCase 总是失败......尽管地址似乎是免费的
【发布时间】:2013-12-16 20:03:18
【问题描述】:

我目前正在清理我的 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,并且我正在使用nose、django-nose、nose-exclude,但我已经有效地将它们切掉以帮助诊断问题。我使用的代码非常简单:

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

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

编辑:今天早上这个问题是不可重现的,任何将端口 8081 标记为打开的东西都不再引起问题。

edit2:在我的文章中将 8081 错误输入为 8082,已修复(并检查以确保我当时输入正确)。

【问题讨论】:

  • 默认端口是8081。

标签: python django


【解决方案1】:

对于它的价值,我遇到了类似的问题,但解决方法略有不同。我们的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 的。在后来的版本中,名称略有变化(我认为是从WSGIServerThreadedWSGIServer)。

【讨论】:

  • 这对我很有帮助,因为我依次从几个文件中运行 selenium 测试。
  • 这正是我所需要的。谢谢。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    如果要分离测试用例,请更改拆卸方法

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

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

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

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

    【讨论】:

    • 这似乎是一个很好的答案,但您需要扩展它,并将代码格式化为代码(选择它并点击 {} 图标)。
    【解决方案4】:

    在前一个测试生成内部服务器错误后运行后续测试时,这开始发生在我身上。在 Mac 上,使用 lsof 找到使用该端口的程序,然后将其杀死。例如:

    $ 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
    

    【讨论】:

      【解决方案5】:

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

        # 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"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-04
        • 1970-01-01
        • 2019-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多