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

Pau*_*gar 19 python unit-testing

我有一个测试用例:

class LoginTestCase(unittest.TestCase):
    ...
Run Code Online (Sandbox Code Playgroud)

我想在不同的测试用例中使用它:

class EditProfileTestCase(unittest.TestCase):
  def __init__(self):
    self.t = LoginTestCase()
    self.t.login()
Run Code Online (Sandbox Code Playgroud)

这引起了:

ValueError: no such test method in <class 'LoginTest: runTest`
Run Code Online (Sandbox Code Playgroud)

我查看了调用异常的unittest代码,看起来测试不应该以这种方式编写.是否有标准的方法来编写您要测试的内容,以便以后的测试可以重用它?或者有解决方法吗?

我现在添加了一个空runTest方法LoginTest作为一个可疑的解决方法.

Gui*_*eim 26

与"runTest"的混淆主要是基于这样的事实:

class MyTest(unittest.TestCase):
    def test_001(self):
        print "ok"

if __name__ == "__main__":
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

因此该类中没有"runTest",并且正在调用所有测试函数.但是,如果您查看基类"TestCase"(lib/python/unittest/case.py),那么您会发现它有一个参数"methodName",默认为"runTest"但它没有默认的实现" def runTest"

class TestCase:
    def __init__(self, methodName='runTest'):
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)


dmv*_*nna 26

这里有一些" 深黑魔法 ":

suite = unittest.TestLoader().loadTestsFromTestCase(Test_MyTests)
unittest.TextTestRunner(verbosity=3).run(suite)
Run Code Online (Sandbox Code Playgroud)

如果您只想测试从shell运行单元测试(即IPython),则非常方便.

  • 除了会发生什么,这是我遇到的问题的实际解决方案!不知道为什么它"在这里"而不是顶部!谢谢 (4认同)

小智 8

如果您不介意直接编辑单元测试模块代码,那么简单的解决方法是在case.pyTestCase下添加一个名为runTest的新方法,该方法不执行任何操作.

要编辑的文件位于pythoninstall\Lib\unittest\case.py下

def runTest(self):
    pass
Run Code Online (Sandbox Code Playgroud)

这将阻止您收到此错误.

  • 这也可以通过在`unittest.TestCase`子类中直接添加这些代码行来实现 (5认同)

saa*_*aaj 5

Guido 的答案几乎就在那里,但它并没有解释这件事。我需要通过unittest代码来掌握流程。

假设您有以下情况。

import unittest

class MyTestCase(unittest.TestCase):

  def testA(self):
    pass

  def testB(self):
    pass
Run Code Online (Sandbox Code Playgroud)

当您使用 时unittest.main(),它会尝试发现当前模块中的测试用例。重要的代码是unittest.loader.TestLoader.loadTestsFromTestCase.

def loadTestsFromTestCase(self, testCaseClass):
  # ...

  # This will look in class' callable attributes that start 
  # with 'test',  and return their names sorted.
  testCaseNames = self.getTestCaseNames(testCaseClass)

  # If there's no test to run, look if the case has the default method.
  if not testCaseNames and hasattr(testCaseClass, 'runTest'):
    testCaseNames = ['runTest']

  # Create TestSuite instance having test case instance per test method.
  loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))

  return loaded_suite
Run Code Online (Sandbox Code Playgroud)

后者所做的是将测试用例类转换为测试套件,该套件根据其测试方法保存类的实例。即我的例子将变成unittest.suite.TestSuite([MyTestCase('testA'), MyTestCase('testB')]). 所以如果你想手动创建一个测试用例,你需要做同样的事情。


Ale*_*lli -9

unittest确实有很深的黑魔法——如果你选择使用它来运行你的单元测试(我这样做,因为这样我可以使用一组非常强大的测试运行器&c集成到我工作场所的构建系统中,但绝对值得替代方案),你最好遵守它的规则。

在这种情况下,我只是EditProfileTestCaseLoginTestCase(而不是直接从unittest.TestCase)派生。LoginTestCase如果您确实希望在不同的环境中测试其中的某些部分EditProfileTestCase,而您不想LoginTestCase在其他环境中进行测试,那么重构这两个部分(可能使用多重继承)是一件简单的事情,并且如果需要发生某些事情在这两种情况下略有不同,将它们分解为辅助“挂钩方法”(在“模板方法”设计模式中)——我经常使用所有这些方法来减少样板文件并增加我总是编写的大量单元测试中的重用(如果我的单元测试覆盖率< 95%,我总是感到真正不安——低于90%,我开始感到身体不适;-)。

  • 它如何回答这个问题?他有没有问过良好报道的美德?为什么不告诉我们如何“按规则行事”?确实是“深层黑魔法”!? (25认同)
  • 向下滚动,这是迄今为止最无用的答案。 (12认同)