ValueError: <class 'myapp.tests.SessionTestCase'>中没有该测试方法: runTest
我有一个测试案例:
class LoginTestCase(unittest.TestCase):
...
我想在另一个测试案例中使用它:
class EditProfileTestCase(unittest.TestCase):
def __init__(self):
self.t = LoginTestCase()
self.t.login()
这引发了:
ValueError: no such test method in <class 'LoginTest: runTest`
我查看了引发异常的unittest代码,发现测试似乎不应该这样写。有没有标准的方法来编写你想要测试的内容,以便后面的测试可以重复使用?或者有没有什么变通的方法?
目前我在LoginTest
中添加了一个空的runTest
方法,作为一个不太可靠的变通办法。
6 个回答
这里有一些深奥的黑科技:
suite = unittest.TestLoader().loadTestsFromTestCase(Test_MyTests)
unittest.TextTestRunner(verbosity=3).run(suite)
如果你只是想从命令行运行你的单元测试,这个方法非常方便(比如用IPython)。
关于“runTest”的困惑主要是因为这个代码可以正常工作:
class MyTest(unittest.TestCase):
def test_001(self):
print "ok"
if __name__ == "__main__":
unittest.main()
在这个类里并没有“runTest”,但是所有的测试函数都被调用了。不过,如果你查看一下基类“TestCase”(lib/python/unittest/case.py),你会发现它有一个参数“methodName”,默认值是“runTest”,但它并没有“def runTest”的默认实现。
class TestCase:
def __init__(self, methodName='runTest'):
之所以unittest.main可以正常工作,是因为它不需要“runTest”。你可以通过为你子类中的所有方法创建一个TestCase的子类实例来模拟这种行为,只需把方法名作为第一个参数提供即可:
class MyTest(unittest.TestCase):
def test_001(self):
print "ok"
if __name__ == "__main__":
suite = unittest.TestSuite()
for method in dir(MyTest):
if method.startswith("test"):
suite.addTest(MyTest(method))
unittest.TextTestRunner().run(suite)
unittest
是个很强大的工具,如果你选择用它来运行单元测试(我用这个,因为它能和我工作中的构建系统很好地结合,提供很多强大的测试运行器等功能,但也有其他不错的选择),那么最好遵循它的规则。
在这种情况下,我建议让 EditProfileTestCase
继承自 LoginTestCase
(而不是直接继承 unittest.TestCase
)。如果你想在 EditProfileTestCase
中测试 LoginTestCase
的某些部分,而有些部分又不想测试,那就可以简单地把 LoginTestCase
拆分成这两部分(可能会用到多重继承)。如果在这两种情况下有些事情需要稍微不同的处理,可以把这些不同的部分提取出来,放到辅助的“钩子方法”中(这是一种“模板方法”的设计模式)——我经常使用这些方法来减少重复代码,提高我写的单元测试的复用性(如果我的单元测试覆盖率低于 95%,我总是会感到不安;低于 90%,我甚至会觉得身体不舒服;-)。