本文介绍了鼻子,unittest.TestCase和元类:未发现自动生成的test_ *方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是针对单元测试和元类的后续问题:自动测试_ *方法生成:

对于此(固定的)unittest.TestCase布局:

For this (fixed) unittest.TestCase layout:

#!/usr/bin/env python

import unittest


class TestMaker(type):

    def __new__(cls, name, bases, attrs):
        callables = dict([
            (meth_name, meth) for (meth_name, meth) in attrs.items() if
            meth_name.startswith('_test')
        ])

        for meth_name, meth in callables.items():
            assert callable(meth)
            _, _, testname = meth_name.partition('_test')

            # inject methods: test{testname}_v4,6(self)
            for suffix, arg in (('_false', False), ('_true', True)):
                testable_name = 'test{0}{1}'.format(testname, suffix)
                testable = lambda self, func=meth, arg=arg: func(self, arg)
                attrs[testable_name] = testable

        return type.__new__(cls, name, bases, attrs)


class TestCase(unittest.TestCase):

    __metaclass__ = TestMaker

    def test_normal(self):
        print 'Hello from ' + self.id()

    def _test_this(self, arg):
        print '[{0}] this: {1}'.format(self.id(), str(arg))

    def _test_that(self, arg):
        print '[{0}] that: {1}'.format(self.id(), str(arg))


if __name__ == '__main__':
    unittest.main()

这可以在stdlib的框架中使用.预期和实际产量:

This works using stdlib's framework. Expected and actual output:

C:\Users\santa4nt\Desktop>C:\Python27\python.exe test_meta.py
Hello from __main__.TestCase.test_normal
.[__main__.TestCase.test_that_false] that: False
.[__main__.TestCase.test_that_true] that: True
.[__main__.TestCase.test_this_false] this: False
.[__main__.TestCase.test_this_true] this: True
.
----------------------------------------------------------------------
Ran 5 tests in 0.015s

OK

但是,由于我实际上是在使用鼻子,因此,这种技巧似乎不同意.我得到的输出是:

However, since I am actually using nose, this trick seems to not agree with it. The output I got is:

C:\Users\santa4nt\Desktop>C:\Python27\python.exe C:\Python27\Scripts\nosetests test_meta.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

简而言之,由元类生成的test_*方法不会向注册鼻子.谁能阐明这一点?

In short, the test_* methods generated by the metaclass do not register with nose. Can anyone shed a light on this?

谢谢

推荐答案

因此,在侦查了stdlib的unittest以及鼻子的加载器和选择器源代码之后,事实证明鼻子可以覆盖unittest.TestLoader.getTestCaseNames来使用自己的选择器(带有插件点).

So, after sleuthing through both stdlib's unittest and nose's loader and selector source code, it turns out that nose overrides unittest.TestLoader.getTestCaseNames to use its own selector (with plugin points).

现在,鼻子的选择器会寻找一种潜在方法的method.__name__来匹配某些正则表达式,黑白列表以及插件的决定.

Now, nose's selector looks for a potential method's method.__name__ to match certain regexes, black and white lists, and plugins' decisions.

就我而言,动态生成的函数具有其testable.__name__ == '<lambda>',与鼻子的选择器条件都不匹配.

In my case, the dynamically generated functions have its testable.__name__ == '<lambda>', matching none of nose's selector criteria.

要修复,

        # inject methods: test{testname}_v4,6(self)
        for suffix, arg in (('_false', False), ('_true', True)):
            testable_name = 'test{0}{1}'.format(testname, suffix)
            testable = lambda self, arg=arg: meth(self, arg)
            testable.__name__ = testable_name    # XXX: the fix
            attrs[testable_name] = testable

果然:

(sandbox-2.7)bash-3.2$ nosetests -vv 
test_normal (test_testgen.TestCase) ... ok
test_that_false (test_testgen.TestCase) ... ok
test_that_true (test_testgen.TestCase) ... ok
test_this_false (test_testgen.TestCase) ... ok
test_this_true (test_testgen.TestCase) ... ok

----------------------------------------------------------------------
Ran 5 tests in 0.005s

OK

这篇关于鼻子,unittest.TestCase和元类:未发现自动生成的test_ *方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 14:20