如何使用“发现”在“测试”目录中运行测试?

时间:2019-04-10 20:10:05

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

使用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.")

4 个答案:

答案 0 :(得分:0)

第一件事:拥有一个__init__.py并不稀奇,因为__init__.py告诉python目录是一个模块。通常有一个空的__init__.py文件。我有同样的错误,并通过重命名目录.来解决。

答案 1 :(得分:0)

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

  

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

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

第二,您正在运行错误的命令python -m unittest discover tests。您不必在末尾添加tests。具有Discover命令的unittests支持4个选项。您可以详细了解here

我具有以下目录结构。

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

我正在运行以下命令。

python3 -m unittest discover

具有以下结果。

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

OK

答案 2 :(得分:0)

如果名为tests.py的文件作为tests模块的同级文件存在,则可能会导致所提到的ImportError,并且删除test.py应该可以解决该问题。

如果仍然没有发现单元测试,则有两个问题需要解决:

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

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

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

所以model_test.py将无法工作;通常用于设置一些伪造的模型,但是单元测试应该放在其他地方。

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

python manage.py test

python manage.py test appname

使用python -m unittest discover代替是否有任何特殊原因?我认为无论哪种方法都可以,但是随后您必须手动引导django环境

答案 3 :(得分:0)

完成...

您已经知道表格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将搜索该环境变量。阅读代码以获取更多详细信息。

我将在此处发布该代码段中的一个示例。

# 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.')