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

现在..

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

怎么做?

【问题讨论】:

    标签: django unit-testing


    【解决方案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
                  

                  因为需要路径

                  【讨论】:

                    猜你喜欢
                    • 2012-06-25
                    • 2012-01-08
                    • 1970-01-01
                    • 2011-09-04
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多