【问题标题】:py.test -n with Django TestCase urlspy.test -n 与 Django TestCase url
【发布时间】:2012-06-11 12:01:32
【问题描述】:

要在 Django 测试中使用特定的 url-config,您只需指定它:

class MyTests(TestCase):
    urls = 'myproj.myapp.urls'

    def test_myurl(self):
        r = self.client.get('/foo/')  # looks up /foo/ in myproj/myapp/urls.py

但它看起来不像是线程安全的实现:

def _urlconf_setup(self):
    if hasattr(self, 'urls'):
        self._old_root_urlconf = settings.ROOT_URLCONF
        settings.ROOT_URLCONF = self.urls
        clear_url_caches()

在我使用 py.test -n8(使用全部 8 个 CPU)运行测试套件后,我在测试日志中看到 404 错误。

有其他人看到/解决过这个问题吗?

【问题讨论】:

    标签: django unit-testing pytest


    【解决方案1】:

    我想知道您使用的默认测试数据库是否保存为一次与 N 个测试进程一起使用

    【讨论】:

    • 我正在使用昨晚备份的挂载副本,所以是的。
    • 我的意思是——例如,如果一个测试进程删除了某些东西,而另一个测试进程想要同时打开会发生什么
    • 这是一个值得关注的问题,但我们已经非常小心地确保了每种测试方法都可以改变数据在单独的记录上工作或创建自己的记录并在之后删除它们。
    【解决方案2】:

    py.test -n8invocation 将启动 8 个子进程。启动 8 个 django 服务器并通过self.client(...) 访问它们是否可能存在问题,即它们每个人都使用一个固定的默认端口?

    更新:另外,您可能想要安装 pytest-django plugin 并查看它是否有助于使用 -n 8 运行您的测试。

    【讨论】:

    • 不,django TestCase 和 Client 的实现只模拟了一个 Web 服务器。在幕后它只使用 WSGI 操作,即没有网络流量发生。
    • pytest-django 插件看起来很有趣。当我们升级到 Django 1.3 时,我会记住这一点 :-(
    【解决方案3】:

    简短的回答:在TestCase 子类上设置urls 在调用from py.test -n 时不是线程安全的,可能是因为不同的线程正在破坏settings.ROOT_URLCONF

    django/core/handlers/base.py:get_response() 中有代码(我也刚刚检查了最新版本),如果存在,它将从请求对象中获取 urlconf,而不是使用settings.ROOT_URLCONF

    那么解决方案是将self.urls 的值附加到Client.py 传递给视图函数的request 对象。实施此修复后,我们使用-n8 运行了 1100 多个测试,没有发现任何问题。

    (如果您已经拥有自己的 client.pytestcases.py 副本,则从 _pre_setup 中删除当前的 urlconf 机制相对容易(~14 loc),而是通过 Client 传递 self.urls 以便 ClientHandler 可以在调用self.get_response()之前将其附加到request。)

    【讨论】:

    • @Ronny 你可能是正确的,但是(没有深入阅读代码)它似乎在可用进程之间分发测试,这样来自不同 urls 的 UnitTest 子类的测试无法重置 Django 的设置代理。如果您有更简单或侵入性较小的解决方案,那就太好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 2011-02-04
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多