如何将 django 单元测试分布在多个文件上?

Posted

技术标签:

【中文标题】如何将 django 单元测试分布在多个文件上?【英文标题】:How to spread django unit tests over multiple files? 【发布时间】:2011-09-09 01:30:09 【问题描述】: 我有一个 python-django 应用程序 我正在使用unit testing framework 测试安排在模块目录下的“tests.py”文件中 我正在通过./manage.py test app 运行测试

现在..

tests.py 文件变得相当大/复杂/混乱 我想将tests.py 分解为更小的测试集合...

怎么做?

【问题讨论】:

【参考方案1】:

请注意,这种方法从 Django 1.6 开始不再有效,请参阅此post。

您可以创建tests 文件夹,其中包含___init___.py(使其成为一个包)。然后在此处添加拆分测试 .py 文件并将它们全部导入___init___.py

即:将test.py 文件替换为外观和行为类似于文件的模块:

在相关应用下创建tests 目录

应用程序 应用\models.py 应用\views.py 应用\测试 应用\测试\__init__.py 应用\测试\香蕉.py 应用\测试\apples.py

将子模块导入app\tests\__init__.py:

from bananas import *
from apples import *

现在您可以使用 ./manage.py,就好像它们都在一个文件中一样:

./manage.py test app.some_test_in_bananas

【讨论】:

多哈。您的意思是在我正在测试的应用程序下创建一个“测试”模块;不是称为测试的新应用程序。我现在明白了。惊人的。谢谢! @John:我再也认不出我的答案了! :-) 但是你完全正确,它太模糊了,即使是正确的——你的例子很清楚,与我原来的措辞相反。 @Tomasz.. 你的话还在那儿——完全完好无损。自从你让我走上正轨后,我才稍微充实了一点。 @John:如果这就是你的意思,我一点也不生气 :) 看到我自己的答案有点不同,这很有趣 @jMyles,如果您所说的“常规 django 测试运行器”是指 python manage.py test myapp,那么实际上这个答案确实可以正常工作。 (刚试过)【参考方案2】:

Django 1.6 中的行为发生了变化,因此不再需要创建包。只需将您的文件命名为 test*.py

From Django 1.7 documentation

运行测试时,测试实用程序的默认行为是 查找所有测试用例(即 unittest.TestCase 的子类) 在任何名称以 test 开头的文件中,自动构建一个测试 套件出这些测试用例,并运行该套件。

来自Django 1.6 documentation,

测试发现基于 unittest 模块的内置测试 发现。默认情况下,这将在任何名为的文件中发现测试 当前工作目录下的“test*.py”。

以前的行为,from Django 1.5 documentation:

运行测试时,测试实用程序的默认行为是 查找所有测试用例(即 unittest.TestCase 的子类) 在 models.py 和 tests.py 中,自动构建一个测试套件 那些测试用例,然后运行那个套件。

还有第二种方法可以为模块定义测试套件:如果你 在 models.py 或 tests.py 中定义一个名为 suite() 的函数, Django 测试运行器将使用该函数来构建测试套件 对于那个模块。这遵循建议的单位组织 测试。有关如何使用的更多详细信息,请参阅 Python 文档 构建一个复杂的测试套件。

【讨论】:

在 django 2.6 中它并没有真正发现任何东西...... 当前使用 Django 1.10,我想将我所有的 test*.py 文件放在一个名为 tests 的文件夹中以保持文件夹清洁 - 这是可能的,但您必须运行 ./manage.py test app.tests 和所有相关文件进口需要上升一个级别(from .models 变为 from ..models)。 将所有文件放入单个文件夹tests,我只使用python manage.py test 开始测试。重要的是,用前缀 test 命名文件夹、类和方法。【参考方案3】:

Tomasz 所说的答案是正确的。但是,确保__init__.py 中的导入与您的文件结构匹配可能会变得乏味。

自动检测文件夹中的所有测试,您可以将其添加到__init__.py

import unittest

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

这将允许您运行./manage.py test appname,但不会处理运行特定测试。为此,您可以使用此代码(也在 __init__.py 中):

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

现在您可以通过manage.py test app 运行所有测试或通过manage.py test app.TestApples 运行特定测试

【讨论】:

第二块放在哪里? 这两部分都进入__init__.py 请注意,如果您的任何测试包名称与在测试运行期间导入的***模块名称一致,则 pkgutil sn-p 将导致导入失败,因为测试被添加为 @987654330 @。一个快速的解决方法是del 任何导致上述问题之后的问题。 (或者你可以重命名你的文件夹;)) 这很好,但我遇到了一个错误,在运行应用程序级别测试 (python manage.py test appName) 时,第二位代码会抛出一个错误,指出 __path__ 不可用。我通过将第二个 sn-p 包装在 if '__path__' in locals(): 检查中来避免它,这起到了作用。感谢您的回答! +1 这也确保 init 文件符合通用编码标准,即没有 * 或未使用的导入【参考方案4】:

只要让你的目录结构像这样:

myapp/
    __init__.py
    tests/
        __init__.py
        test_one.py
        test_two.py
        ...
    ...

python manage.py test myapp 将按预期工作。

【讨论】:

【参考方案5】:

http://docs.python.org/library/unittest.html#organizing-tests 谈到将文件拆分为模块,上面的部分有一个示例。

【讨论】:

我在 rtfm 上寻找的 'bit extra' 是用于测试的 django 设置环境、数据库和固定装置。【参考方案6】:

使用 Django 2.2 一个简单且相当好的解决方案可能是在应用程序中创建一个 test 文件夹,您可以将相关的 test_...py 文件放入,只需将 __init__.py 添加到 test 文件夹即可。

【讨论】:

【参考方案7】:

无需在 init 中编写任何代码。 只需在您的应用程序中创建一个子目录。唯一的要求是不要称之为测试* 例如

app/
app/__init_.py
app/serializers.py
app/testing/
app/testing/__init__.py
app/testing/tests_serializers.py

【讨论】:

为什么不能称它为以“测试”开头的东西? 我在 Django 1.11.4 中使用这个答案。使用它的原因:(1)文件“app/testing/__init__.py”保持为空,(2)命令保持基本的“python manage.py test app”【参考方案8】:

如果你有一个更复杂的设置,或者不想使用from ... import *-type 语句,你可以在你的tests.py(或tests/__init__.py)中定义一个名为suite的函数,它返回unittest.TestSuite 的一个实例。

【讨论】:

【参考方案9】:

我有两个文件。一个是tests.py,另一个是test_api.py。我可以按如下方式单独运行这些。

manage.py test companies.tests
manage.py test companies.test_api

参考@osa 对文件命名约定的回复。

【讨论】:

【参考方案10】:

我认为./manage.py test 只是运行所有测试技巧(在 django >= 1.7 中)。

如果您的组织测试是关于分组樱桃采摘,并且你是nose的粉丝,请使用django nose:

python manage.py test another.test:TestCase.test_method

如果您知道鼻子,那么您就知道如何更好地“通配符”您的所有文件。

PS

这只是一种更好的做法。希望有帮助。答案是从这里借来的:Running a specific test case in Django when your app has a tests directory

【讨论】:

【参考方案11】:

在 django 中,您可以使用下面的命令或查看documentation。此外,使用此命令将获取具有您提供的模式的文件,而不仅仅是 test*.pytest_*.py。

文档 如果您的测试文件的名称与 test*.py 模式不同,您可以使用 -p(或 --pattern)选项指定自定义文件名模式匹配:

$ ./manage.py test --pattern="tests_*.py"

【讨论】:

【参考方案12】:

只需在您的应用中使用 tests_name 创建不同的测试文件

假设您有以下测试文件:

tests_admins.py
tests_staff.py
tests_others.py
# will run both test files
(venv)..yourapp$./manage.py test --keepdb -v 2 appname

【讨论】:

【参考方案13】:

或者在 Windows 中,如果您不想创建一个包(即带有 __init__.py 的文件夹)并且只想创建一个名为“Tests”的文件夹并且该文件夹包含测试文件,那么在 cmd 中运行测试只需输入

python manage.py test your_app_name/Tests

因为需要路径

【讨论】:

以上是关于如何将 django 单元测试分布在多个文件上?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中使用不同的设置进行单元测试?

如何在多个 django 应用程序中使用单例实例

多个进程之间的单元测试交互

Django:从根目录开始的多个 url 模式分布在文件中

如何在 Xcode 7 中动态更改单元测试的目标?

如何为具有多个模式分布的Controller编写单元测试