2013-03-07 44 views
3

我想为TestCase派生类的变体创建一个生成器。鼻子:基于TestCase的类的生成器

我想这是什么:

import unittest 

def create_class(param): 
    class Test(unittest.TestCase): 
     def setUp(self): 
      pass 

     def test_fail(self): 
      assert False 
    return Test 

def test_basic(): 
    for i in range(5): 
     yield create_class(i) 

我得到的是这样的:

====================================================================== 
ERROR: test_1.test_basic 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/lib/python3.3/site-packages/nose/case.py", line 268, in setUp 
    try_run(self.test, names) 
    File "/usr/lib/python3.3/site-packages/nose/util.py", line 478, in try_run 
    return func() 
TypeError: setUp() missing 1 required positional argument: 'self' 

屈服实例,而不是类(yield create_class(i)())给我留下了这个错误:

====================================================================== 
ERROR: test_1.test_basic 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/lib/python3.3/site-packages/nose/case.py", line 198, in runTest 
    self.test(*self.arg) 
    File "/usr/lib/python3.3/unittest/case.py", line 492, in __call__ 
    return self.run(*args, **kwds) 
    File "/usr/lib/python3.3/unittest/case.py", line 423, in run 
    testMethod = getattr(self, self._testMethodName) 
AttributeError: 'Test' object has no attribute 'runTest' 

有什么建议吗?

回答

4

当实例化一个TestCase,你应该通过测试的方法名称:

yield create_class(i)('test_fail') 

否则,该名称默认为runTest(因而最后你得到的错误)。

另请注意,测试生成器与TestCase之间存在奇怪的相互作用。用下面的代码:

import unittest 

def create_class(param): 
    class Test(unittest.TestCase): 
     def setUp(self): 
      pass 

     def test_fail(self): 
      print('executed') 
      assert False 
      print('after assert') 

    return Test 

def test_basic(): 
    for i in range(5): 
     yield create_class(i)('test_fail') 

我获得此输出:

$ nosetests -s 
executed 
.executed 
.executed 
.executed 
.executed 
. 
---------------------------------------------------------------------- 
Ran 5 tests in 0.004s 

OK 

正如你可以看到测试不会失败,即使assert作品。这可能是由于TestCase处理了AssertionError这一事实,但nose并不指望这样处理,因此它不能看到测试失败。

这可以从TestCase.run的文件中可以看出:

Run the test, collecting the result into the test result object passed as result . If result is omitted or None, a temporary result object is created (by calling the defaultTestResult() method) and used. The result object is not returned to run() ‘s caller.

The same effect may be had by simply calling the TestCase instance. 

所以,nose没有看到反对由发电机产生是TestCase应在一个特殊的方式来处理,它只是希望一个可调用的。运行TestCase,但结果被放入临时对象中,并且这会消耗测试中发生的所有测试失败。因此产生TestCase es根本不起作用。

+0

如果我在'Test'中有多个方法,该怎么办?明确地传递这些信息似乎是对DRY原则的一大破坏...... – dom0 2013-03-07 21:33:38

+0

@ dom0我认为你应该仔细阅读关于[测试生成器]的鼻子文档(https://nose.readthedocs.org/en/latest/writing_tests.html#test -generators)。你在混合东西。 'TestCase's *不是*被设计用于这种方式,显然这导致次优代码。 – Bakuriu 2013-03-07 21:38:03

0

我已经运行您提供的代码。我没有收到任何错误。我使用的版本是python2.7。系统是ubuntu12.10。也许你需要检查python2.7。

+0

好吧然后这对我来说似乎是一个错误。我使用Python 3.3的鼻子,也许这是问题。我不能(也不想)将项目切换回Python 2.x,所以我只是尝试解决这个问题的同时...... – dom0 2013-03-07 21:27:48