我该如何使用unittest.TestResult?

11

我只是短暂地使用unittest。我正在使用Jython 2.7.10“最终发布版”。

在Python 2.7文档中解释TestResult时,它说:

TestResult类的以下方法用于维护内部数据结构,并且可以在子类中进行扩展以支持其他报告要求。这对于在运行测试时构建支持交互式报告的工具非常有用。

startTest(test) ... stopTest(test) ... startTestRun() ... stopTestRun()¶

这就是我想做的... 但我不知道如何使用TestResult。下面是一个SSCCE示例...

import unittest

class TestResultX( unittest.TestResult ):
    def startTest( self, test ):
        print( '# blip')
        unittest.TestResult.startTest( self, test )
    def stopTest( self, test ):
        print( '# blop')
        unittest.TestResult.stopTest( self, test )
    def startTestRun( self ):
        print( '# blep')
        unittest.TestResult.startTestRun( self )
    def stopTestRun( self ):
        print( '# blap')
        unittest.TestResult.stopTestRun( self )

class TestCaseX( unittest.TestCase ):
    def test_nonsense(self):
        print( '# wotcha' )
        self.assertTrue( False )

    def run( self, test_result=None ):
        print( '# spoons starting...')

        test_result = TestResultX()
        unittest.TestCase.run( self, test_result )

        print( '# ...spoons ended, tr %s' % ( test_result,  ) )

unittest.main()

结果是:

# spoons starting...

----------------------------------------------------------------------
Ran 0 tests in 0.015s

OK
# blip
# wotcha
# blop
# ...spoons ended, tr <__main__.TestResultX run=1 errors=0 failures=1>

问题:

  • 为什么显示为0 tests
  • blepblap(运行的开始和结束)为什么没有打印出来?

更一般地说:

  1. 有人可以指点一下好的教程/书籍,解释TestResult、TestRunner、TestLoader等的“正确使用”/“最佳实践”吗?我看了《Python TDD》,但似乎没有解释这些。

  2. 有人可以告诉我为什么经常使用unittest2而不是unittest吗?

附录

在Omar Diab查看源代码的努力之后,我尝试了这个:

def run( self, *args, **kvargs ):
    result = self.defaultTestResult()
    startTestRun = getattr(result, 'startTestRun', None)
    logger.info( '# calling superclass run... startTestRun? %s' % ( startTestRun, ))
    unittest.TestCase.run( self, *args, **kvargs  )
    logger.info( '# ... superclass run ended')

很不幸,每个 test_XXX 方法都返回了以下结果:

# calling superclass run... startTestRun? <bound method TestResult.startTestRun of <unittest.result.TestResult run=0 errors=0 failures=0>>

setUp for test_that_stuff_happened (__main__.xx_FT)

tearDown for test_that_stuff_happened (__main__.xx_FT)
end tearDown...
. # ... superclass run ended

1
我遇到了这个问题 - 必须说,所有这些的文档都非常糟糕... - osdiab
3个回答

3

哇,没有回应。我很惊讶。

这是一个技巧,大多数人可能可以自己解决,如果你想在运行开始和结束时发生一些事情:

按照以下方式创建TestCase的子类:

def setUp( self ):
    if not hasattr( unittest.TestCase, 'app' ):
        unittest.TestCase.app = MyApp()
        def shutdown_func():
            pass # do any end-of-run stuff here
        atexit.register( shutdown_func )
        pass # do any start-of-run stuff here
    self.app = unittest.TestCase.app

然后让所有的TestCases都从这个类继承...

重点是,如果你希望这样做,那么你的应用程序只会被构建一次。当然,确保每个连续的setUp都是“原始”的责任取决于你。 显然,你可以使用setUpClass,但是那样你就无法访问TestCase实例。


我不太明白如何使用你的示例。能否提供一个简洁的工作示例? - user

3

我遇到了同样的问题,所以我查看了源代码。

检查 unittest.TextTestRunnerunittest.TestCase,看起来 startTestRun()stopTestRun() 是手动调用的。在 unittest.TextTestRunner 中,它的工作方式如下:

def run(self, test):
    # ...
    startTestRun = getattr(result, 'startTestRun', None)
    if startTestRun is not None:
        startTestRun()
    # ...

在你的情况下,unittest.TestCase 的用法如下:
def run(self, result=None):
    orig_result = result
    if result is None:
        result = self.defaultTestResult()
        startTestRun = getattr(result, 'startTestRun', None)
        if startTestRun is not None:
            startTestRun()
    # ...

所以看起来startTestRun只有在你不传递result时才会被TestCase.run()调用。你正在传递result,所以它没有发生。
这对我来说似乎是个bug!但基本上它意味着你可以扩展TestCaseTestSuite,重新实现运行方法,然后手动调用那些方法;或者只是在那些相应的run方法之外调用它们。
希望这能帮到你!

感谢查看源代码。当然,我本应该自己这样做!不幸的是,您重新设计run方法的建议对我没有起作用。请参见我在原始帖子中添加的附录... - mike rodent

-1

认为在TestCase.run()中创建TestResult对象被误解为无法访问流、描述和冗长度。将其作为KWarg提供即可解决问题。

def run( self, test_result=TestResultX ):
or create TestResult in Runner.run():

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接