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

时间:2015-04-21 15:10:46

标签: python django unit-testing nose

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

实际上,测试类和方法是在运行时生成w / type(以考虑辅助文件中列出的数据)。我正在以下列方式做事(请参阅下面的更多代码):

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

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

我想要做的只是运行部分测试,而不是手动列出他们的名字

例如,我可以在类名或方法名中给每个测试“标签”,以便我可以对它们进行过滤。例如,我将执行:运行所有测试哪个方法名称包含字符串“test_postgres_backend _”

我尝试使用django-nose因为nose的{​​{1}}选项,它应该能够根据正则表达式选择测试,这是解决我问题的理想方法。

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

  • -m没有自动查找./manage.py test myapp生成的测试类(与django测试运行器相反)
  • type./manage.py test -m ".*" myapp都找不到任何测试,即使文件中存在普通./manage.py test myapp -m ".*"

所以:

  • 您是否对我的一般问题有另一种解决方案,而不是尝试使用django-nose TestCase
  • 使用-m,您知道如何使django-nose正常工作吗?

MCVE

将以下内容添加到空的-m文件中:

myapp/tests.py

如果通过django test runnner运行此输出的运行(按字母顺序排列):
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)

如果您更改为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上没有任何操作。

修复此问题后,我希望只能运行名称以./manage.py test myapp 结尾的测试方法(或其他类型的可重用过滤)

2 个答案:

答案 0 :(得分:5)

您遇到的问题是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会将两个顶级函数视为模块级测试,并将另外运行到类中的测试中。< / p>

获得相同结果的另一种方法是在两个函数上定义__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平等地匹配文件,directorie,模块,类和函数名称。如果您设置类似-m0$然后 all 的内容,我刚刚列出的各个部分必须与要选择的测试的正则表达式匹配。 (Nose不会将它们组合在一起然后在组合上匹配。)可以在命令行上单独列出测试,但这不能替代正则表达式匹配。

答案 1 :(得分:2)

通常,您可以使用以下内容运行特定测试:

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

你尝试过这种方法吗?