【问题标题】:How do I use "discover" to run tests in my "tests" directory?如何使用“discover”在我的“tests”目录中运行测试?
【发布时间】:2019-09-01 09:17:17
【问题描述】:

使用 DJango/Python 3.7。我在这里读到——How do I run all Python unit tests in a directory? 我可以使用“发现”命令在指定目录中查找测试。我想要一个“测试”文件夹,所以我创建了一个然后运行

(venv) localhost:myproject davea$ python -m unittest discover tests
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/__main__.py", line 18, in <module>
    main(module=None)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 100, in __init__
    self.parseArgs(argv)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 124, in parseArgs
    self._do_discovery(argv[2:])
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 244, in _do_discovery
    self.createTests(from_discovery=True, Loader=Loader)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 154, in createTests
    self.test = loader.discover(self.start, self.pattern, self.top)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 344, in discover
    raise ImportError('Start directory is not importable: %r' % start_dir)
ImportError: Start directory is not importable: 'tests'

这对我来说很奇怪,因为我有一个(空的)初始化文件...

(venv) localhost:myproject davea$ ls web/tests/
__init__.py  model_tests.py

我还需要做什么才能让我的测试目录被识别?

编辑:下面是model_tests.py的内容...

from django.conf import settings
from django.test import TestCase
from django.core import management


def setup():
    print("setup")
    management.call_command('loaddata', 'test_data.yaml', verbosity=0)


def teardown():
    management.call_command('flush', verbosity=0, interactive=False)


class ModelTest(TestCase):

    # Verify we can correctly calculate the amount of taxes when we are working
    # with a state whose tax rates are defined in our test data
    def test_calculate_tax_rate_for_defined_state(self):
        state = "MN"
        income = 30000
        taxes = IndividualTaxBracket.objects.get_taxes_owed(state, income)
        print(taxes)
        self.assertTrue(taxes > 0, "Failed to calucate taxes owed properly.")

【问题讨论】:

  • 您的tests 目录位于web 目录中,因此您可能需要在运行命令之前cd 进入该目录。
  • 您是否忘记了一个空的“tests.py”文件作为“tests”文件夹的同级文件?
  • @MarioOrlandi,我确实在“tests”旁边有一个“tests.py”文件,这导致了一些错误,所以我继续删除了它。但是我仍然无法运行测试或仅针对 model_tests.py 中的测试。
  • 戴夫,有几个问题是有序的......我会添加一个更好的文本格式的答案......

标签: django python-3.x unit-testing testing


【解决方案1】:

为了完成……

你已经知道那个表格here

您的测试和文件的名称必须与特定模式匹配才能被discover() 发现。

但是你得到了这个错误:

“django.core.exceptions.ImproperlyConfigured:请求设置,但未配置设置”

这意味着 Django 在运行测试时无法找到它的设置。您可以使用环境变量告诉在哪里可以找到设置:

DJANGO_SETTINGS_MODULE='myproyect.settings' python3 -m unittest discover

参考:https://docs.djangoproject.com/en/2.2/topics/settings/#designating-the-settings

另一方面...

您应该使用

运行 Django 测试
./manage.py tests

这将search tests automatically using the same mechanism than discover(),并且由于您将运行 Django 命令,因此您将比直接运行 Django 测试有一些好处。


@Nafees Anwar 问:设置环境变量如何配置设置?

model_tests.py 文件的最开始有from django.conf import settings 行,在创建设置LazyObject 实例时,Django 将搜索该环境变量。阅读代码了解更多详情。

我将在此处发布该代码中的 sn-p 以进行说明。

# django.conf module.
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"


class LazySettings(LazyObject):
    """
    A lazy proxy for either global Django settings or a custom settings object.
    The user can manually configure settings prior to using them. Otherwise,
    Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
    """
    def _setup(self, name=None):
        """
        Load the settings module pointed to by the environment variable. This
        is used the first time we need any settings at all, if the user has not
        previously configured the settings manually.
        """
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        if not settings_module:
            desc = ("setting %s" % name) if name else "settings"
            raise ImproperlyConfigured(
                "Requested %s, but settings are not configured. "
                "You must either define the environment variable %s "
                "or call settings.configure() before accessing settings."
                % (desc, ENVIRONMENT_VARIABLE))

        self._wrapped = Settings(settings_module)

如果你这样做:

from django.conf import settings

解决了那个环境变量,声明

settings.configure()

将因RuntimeError('Settings already configured.') 而失败

【讨论】:

  • 如何设置环境变量configure's settings
  • model_tests.py 文件的最开始有from django.conf import settings 行,在创建settings LazyObject 实例时,django 将搜索该环境变量。阅读代码了解更多详情。
【解决方案2】:

如果一个名为 tests.py 的文件作为 tests 模块的兄弟存在,这可能会导致提到的 ImportError,删除 test.py 应该可以解决它。

如果仍然没有发现单元测试,那么有几个问题:

1) 测试模块是否至少包含一个派生自 django.test.TestCase 的类?

2) 在这种情况下,该类是否包含至少一个名称以“test_”开头的方法

请注意,任何包含单元测试的文件的名称都应以“test”开头。

所以 model_test.py 将不起作用; is 通常用于设置一些假模型,但单元测试应该驻留在其他地方。

您可以使用此管理命令发现并运行测试:

python manage.py test

python manage.py test appname

使用python -m unittest discover 有什么特别的原因吗?我认为这也可以,但是您必须手动引导 django 环境

【讨论】:

  • 我编辑了我的问题以包含我的 model_tests.py 文件。类行看起来像“class ModelTest(TestCase)”,所以我“认为”它继承自您指定的内容,但也许还有其他事情我不知道。
  • @Dave 我认为您需要重命名 model_tests.py 以便有机会在其中发现单元测试。任何以“test”开头的东西都可以。此外,将 setup() 移动到名为 setUp(self) 的类方法中,将 teardown() 移动到名为 tearDown(self) 的方法中。我用更多提示详细说明了我的答案。祝你好运;)
【解决方案3】:

第一件事:拥有__init__.py 并不罕见,因为__init__.py 告诉python 该目录是一个模块;通常有一个空的__init__.py 文件。我遇到了同样的错误,并通过重命名我的目录 . 来修复它。

【讨论】:

  • 你能具体说明一下这是什么意思吗?我是 python 新手。
【解决方案4】:

我认为您对discover 命令有些困惑。根据文档。

Unittest 支持简单的测试发现。为了兼容 使用测试发现,所有测试文件必须是模块或包 (包括命名空间包)可从顶级目录导入 项目的(这意味着他们的文件名必须是有效的 标识符)。

这意味着所有测试文件都必须可导入从您运行命令的目录(包含您的web 目录的目录)。它确保所有测试文件都必须位于有效的 python 包中(包含__init__.py 的目录)。

其次,您正在运行命令python -m unittest discover tests,这是错误的。您不必在末尾添加tests。带有 discover 命令的单元测试支持 4 个选项。你可以阅读更多关于它的信息here

我有以下目录结构。

 web
    ├── __init__.py
    └── tests
        ├── __init__.py
        └── test_models.py

我正在运行以下命令。

python3 -m unittest discover

结果如下。

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

【讨论】:

  • 所以我运行“python -m unittest discover”并得到消息“在 0.000 秒内运行 0 个测试”。我需要做什么/添加什么才能真正运行我的 model_tests.py 文件中的测试?
  • @Dave python 实际上只从特定文件中发现测试。用于此发现的模式是 test*.py,这意味着您的测试文件应该从 test 字开始。喜欢test_models.pytest_views.py。您可以使用 -p 标志覆盖此模式。就像如果您更喜欢在文件名末尾进行测试,例如model_tests.py,您可以这样做。 python -m unittest discover -p "*_tests.py".
  • 我将测试的名称更改为您推荐的名称,但现在我收到错误消息“django.core.exceptions.ImproperlyConfigured:请求的设置,但未配置设置”。我不知道这是否与你所拥有的有关,所以我打开了一个单独的问题——stackoverflow.com/questions/55696337/…
  • 啊!所以你正在尝试用 python 运行 django 测试?你不能很容易地做到这一点。我很惊讶你为什么不使用 django 的内置工作流来运行测试?不过我建议你这样做。 from django.conf import settings 然后 settings.configure() 在您的测试包的 __init__.py 文件中。但我怀疑会弹出一些其他错误。我强烈推荐你使用 django 的内置测试设置。
  • 哦,Django的运行测试方式不涉及“manage.py”文件?我对所有这些教程感到困惑。
猜你喜欢
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
相关资源
最近更新 更多