代码之家  ›  专栏  ›  技术社区  ›  Paul Biggar

valueerror:在<class'myapp.tests.sessiontestcase'>中没有此类测试方法:runtest

  •  19
  • Paul Biggar  · 技术社区  · 14 年前

    我有一个测试用例:

    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代码,看起来测试不应该这样编写。有没有一种标准的方法来编写您想要测试的东西,以便以后的测试可以重用它?还是有解决办法?

    我加了一个空的 runTest 方法到 LoginTest 作为一个可疑的解决办法。

    6 回复  |  直到 6 年前
        1
  •  -6
  •   Alex Martelli    14 年前

    unittest 做深黑色魔法——如果你选择使用它来运行你的单元测试(我做了,因为这样我可以使用一个非常强大的测试运行器电池&c集成到我的工作场所的构建系统中,但是肯定有值得选择的),你最好按照它的规则来做。

    在这种情况下,我只需要 EditProfileTestCase 源自 LoginTestCase (而不是直接从 unittest.TestCase )如果有 登录实例 您确实希望在 EditProfileTestCase ,以及其他不需要的,重构是一件简单的事情 登录实例 在这两个部分中(可能使用多重继承),如果在这两种情况下有些事情需要稍微不同的发生,将它们分解成辅助的“钩子方法”(在“模板方法”设计模式中)——我经常使用所有这些方法来减少样板文件并增加重用在大量的单元测试中,我总是写作(如果我有单元测试覆盖率<95%,我总是感到非常不安——低于90%,我开始感到身体不适;-)。

        2
  •  26
  •   Guido U. Draheim    11 年前

    与“runtest”的混淆主要基于这样一个事实:

    class MyTest(unittest.TestCase):
        def test_001(self):
            print "ok"
    
    if __name__ == "__main__":
        unittest.main()
    

    所以在这个类中没有“runtest”,所有的测试函数都被调用。但是,如果查看基类“testcase”(lib/python/unittest/case.py),您会发现它有一个默认为“runtest”的参数“methodname”,但它没有默认的“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)
    
        3
  •  24
  •   dmvianna    9 年前

    这是一些 深黑魔法 “:

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

    如果您只想从shell(即, IPython )

        4
  •  8
  •   Darren McMillan    9 年前

    如果您不介意直接编辑单元测试模块代码,简单的解决方法是在 案例.py 测试用例 一个叫做runtest的新方法什么也不做。

    要编辑的文件位于pythonninstall\lib\unittest\case.py下

    def runTest(self):
        pass
    

    这将阻止你得到这个错误。

        5
  •  4
  •   saaj    10 年前

    圭多的答案几乎就在那里,但它没有解释这件事。我需要注意 unittest 掌握流程的代码。

    假设你有下面这些。

    import unittest
    
    class MyTestCase(unittest.TestCase):
    
      def testA(self):
        pass
    
      def testB(self):
        pass
    

    当你使用 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
    

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

        6
  •  4
  •   Community Egal    7 年前

    @Dmvianna的回答让我几乎可以跑了 unittest 在一个笔记本里,但我还得做更多。如果我只写了以下内容:

    class TestStringMethods(unittest.TestCase):
    
        def test_upper(self):
            self.assertEqual('foo'.upper(), 'FOO')
    
        def test_isupper(self):
            self.assertTrue('FOO'.isupper())
            self.assertFalse('Foo'.isupper())
    
        def test_split(self):
            s = 'hello world'
            self.assertEqual(s.split(), ['hello', 'world'])
            # check that s.split fails when the separator is not a string
            with self.assertRaises(TypeError):
                s.split(2)
    
    suite = unittest.TestLoader().loadTestsFromModule (TestStringMethods)
    unittest.TextTestRunner().run(suite)
    

    我得到了


    在0.000秒内运行0个测试

    好啊

    它没有坏,但是它没有运行任何测试!如果我实例化了测试类

    suite = unittest.TestLoader().loadTestsFromModule (TestStringMethods())
    

    (注意行末的括号,这是唯一的变化)我得到了


    值错误回溯(最近一次调用) 在() --->1套件=unittest.testloader().loadtestsfrommodule(teststringmethods())

    /usr/lib/python2.7/unittest/case.pyc输入 初始化 (self,方法名) 189除属性错误: 190 raise valueerror(“在%s中没有这样的测试方法:%s”% -->191(自我。 ,方法名) 192 self.\u testmethoddoc=测试方法。 doc 193个self._cleanups=[]

    valueerror:runtest中没有此类测试方法

    解决方案现在相当清楚了:添加 runTest 对于测试类:

    class TestStringMethods(unittest.TestCase):
    
        def runTest(self):
            test_upper (self)
            test_isupper (self)
            test_split (self)
    
        def test_upper(self):
            self.assertEqual('foo'.upper(), 'FOO')
    
        def test_isupper(self):
            self.assertTrue('FOO'.isupper())
            self.assertFalse('Foo'.isupper())
    
        def test_split(self):
            s = 'hello world'
            self.assertEqual(s.split(), ['hello', 'world'])
            # check that s.split fails when the separator is not a string
            with self.assertRaises(TypeError):
                s.split(2)
    
    suite = unittest.TestLoader().loadTestsFromModule (TestStringMethods())
    unittest.TextTestRunner().run(suite)
    

    在0.002s中运行3个测试

    好啊

    如果 运行测试 只是 pass 是的,正如@darren建议的那样。

    这有点恶心,我需要一些体力劳动,但也更多 明确的 ,这是蟒蛇的美德,不是吗?

    我打电话找不到任何技巧 unittest.main 从这里或从这个相关的问题中有明确的论据 Unable to run unittest's main function in ipython/jupyter notebook 在Jupyter笔记本里工作,但我又带着满满的油箱上路了。