ValueError: <class 'myapp.tests.SessionTestCase'>中没有该测试方法: runTest

21 投票
6 回答
19260 浏览
提问于 2025-04-15 18:11

我有一个测试案例:

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 个回答

27

这里有一些深奥的黑科技

suite = unittest.TestLoader().loadTestsFromTestCase(Test_MyTests)
unittest.TextTestRunner(verbosity=3).run(suite)

如果你只是想从命令行运行你的单元测试,这个方法非常方便(比如用IPython)。

28

关于“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)
-9

unittest 是个很强大的工具,如果你选择用它来运行单元测试(我用这个,因为它能和我工作中的构建系统很好地结合,提供很多强大的测试运行器等功能,但也有其他不错的选择),那么最好遵循它的规则。

在这种情况下,我建议让 EditProfileTestCase 继承自 LoginTestCase(而不是直接继承 unittest.TestCase)。如果你想在 EditProfileTestCase 中测试 LoginTestCase 的某些部分,而有些部分又不想测试,那就可以简单地把 LoginTestCase 拆分成这两部分(可能会用到多重继承)。如果在这两种情况下有些事情需要稍微不同的处理,可以把这些不同的部分提取出来,放到辅助的“钩子方法”中(这是一种“模板方法”的设计模式)——我经常使用这些方法来减少重复代码,提高我写的单元测试的复用性(如果我的单元测试覆盖率低于 95%,我总是会感到不安;低于 90%,我甚至会觉得身体不舒服;-)。

撰写回答