运行 特定的 Django 测试(使用 django-nose?)

Run specific Django tests (with django-nose?)

我有一个非常复杂的 tests.py 文件。

实际上,测试 classes 和方法是在 运行 时间和 type 生成的(考虑辅助文件中列出的数据)。我正在按照以下方式做事(更多代码见下文):

klass = type(name, (TestCase,), attrs)
setattr(current_module, name, klass)

仅供参考,使用通常的 django 测试 运行ner,所有这些测试在执行 ./manage.py test myapp 时都会得到 运行(感谢上面显示的 setattr)。

我想做的只是运行那些测试的一部分,而不是手工列出他们的名字.

例如,我可以在 class 名称或方法名称中给每个测试 "tags" 以便我可以对它们进行过滤。例如,我将执行: 运行 所有方法名称包含字符串 "test_postgres_backend_"

的测试

我尝试使用 django-nose 因为 nose-m 选项,它应该能够 select 基于正则表达式的测试,一个理想的解决方案问题。

不幸的是,这是使用 django-nose 作为 django 测试时发生的事情 运行ner:

所以:


mcve

将以下内容添加到一个空的 myapp/tests.py 文件中:

from django.test import TestCase
from sys import modules


current_module = modules[__name__]


def passer(self, *args, **kw):
    self.assertEqual(1, 1)


def failer(self, *args, **kw):
    self.assertEqual(1, 2)


# Create a hundred ...
for i in xrange(100):
    # ... of a stupid TestCase class that has 1 method that passes if `i` is
    # even and fails if `i` is odd
    klass_name = "Test_%s" % i
    if i % 2:  # Test passes if even
        klass_attrs = {
            'test_something_%s' % i: passer
        }
    else:      # Fail if odd
        klass_attrs = {
            'test_something_%s' % i: failer
        }
    klass = type(klass_name, (TestCase,), klass_attrs)

    # Set the class as "child" of the current module so that django test runner
    # finds it
    setattr(current_module, klass_name, klass)

如果通过 django test 运行nner:
生成此输出 运行(按 alphab 顺序) F.F.F.F.F.F.FF.F.F.F.F..F.F.F.F.F.FF.F.F.F.F..F.F.F.F.F.FF.F.F.F.F..F.F.F.F.F.FF.F.F.F.F..F.F.F.F.F..

如果你改成django_nose测试运行ner,./manage.py test myapp.

没有任何反应

修复此问题后,我希望能够 运行 仅名称以 0(或其他一些名称)结尾的测试方法一种正则表达式过滤)

一般来说,您可以 运行 您的特定测试,如下所示:

# assuming your tests are in core/tests.py
python manage.py test core.tests:CoreTestCase.my_specific_test

你试过这种方法吗?

您 运行 遇到的问题是 Nose 通过查看函数上记录的 名称来确定是否将方法包含到 运行 的测试集中本身,而不是提供对函数的访问权限的属性 。如果我将您的 passerfailer 重命名为 test_passtest_fail 那么 Nose 就能够找到测试。因此,函数本身的命名方式必须与 -m(或其默认值)相匹配。

这是给出预期结果的修改后的代码:

from django.test import TestCase
from sys import modules

current_module = modules[__name__]

def test_pass(self, *args, **kw):
    self.assertEqual(1, 1)

def test_fail(self, *args, **kw):
    self.assertEqual(1, 2)

# Create a hundred ...
for i in xrange(100):
    # ... of a stupid TestCase class that has 1 method that passes if `i` is
    # even and fails if `i` is odd
    klass_name = "Test_%s" % i
    if i % 2:  # Test passes if even
        klass_attrs = {
            'test_something_%s' % i: test_pass
        }
    else:      # Fail if odd
        klass_attrs = {
            'test_something_%s' % i: test_fail
        }
    klass = type(klass_name, (TestCase,), klass_attrs)

    # Set the class as "child" of the current module so that django test runner
    # finds it
    setattr(current_module, klass_name, klass)

# This prevents Nose from seeing them as tests after the loop is over.
test_pass = None
test_fail = None

如果没有对 None 的最后两个赋值,Nose 会将这两个顶级函数视为模块级测试,并将 运行 它们 另外 到 classes.

中的测试

获得相同结果的另一种方法是在您的两个函数上定义 __test__

def passer(self, *args, **kw):
    self.assertEqual(1, 1)
passer.__test__ = 1

def failer(self, *args, **kw):
    self.assertEqual(1, 2)
failer.__test__ = 1

并在文件末尾:

# This prevents Nose from seeing them as tests after the loop is over.
passer = None
failer = None

Nose 在函数中寻找这些函数的存在,如果存在并设置为一个值被认为是真实的,它将把函数作为测试用例。

可以在 Nose 的 selector.py 文件中找到控制方法选择的逻辑,位于 wantMethod method:

def wantMethod(self, method):
        """Is the method a test method?
        """
        try:
            method_name = method.__name__
        except AttributeError:
            # not a method
            return False
        if method_name.startswith('_'):
            # never collect 'private' methods
            return False
        declared = getattr(method, '__test__', None)
        if declared is not None:
            wanted = declared
        else:
            wanted = self.matches(method_name)
        plug_wants = self.plugins.wantMethod(method)
        if plug_wants is not None:
            wanted = plug_wants
        log.debug("wantMethod %s? %s", method, wanted)
        return wanted

我没有看到使用 -m 到 运行 的明确方法,只能按照您想要的方式进行一些测试。问题是 -m 匹配文件、目录、模块、class 和函数名。如果你设置类似 -m0$ 然后 all 我刚刚列出的各个部分必须匹配要选择的测试的正则表达式。 (Nose 不会将它们组合起来,然后在组合上进行匹配。)可以在命令行上单独列出测试,但这是对正则表达式匹配的糟糕替代。