简体   繁体   English

我如何使用unittest.TestResult?

[英]How do I use unittest.TestResult?

I've only been using unittest for a short time. 我只是在短时间内使用unittest。 I am using Jython 2.7.10 "final release" 我正在使用Jython 2.7.10“最终版本”

In the Python 2.7 docs explaining TestResult it says: 在解释TestResult的Python 2.7文档中,它说:

The following methods of the TestResult class are used to maintain the internal data structures, and may be extended in subclasses to support additional reporting requirements. TestResult类的以下方法用于维护内部数据结构,并且可以在子类中进行扩展以支持其他报告要求。 This is particularly useful in building tools which support interactive reporting while tests are being run. 这对于构建在运行测试时支持交互式报告的工具特别有用。

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

That's what I want to do... but I can't work out how you use TestResult. 这就是我想要做的......但我无法弄清楚你如何使用TestResult。 Here's an SSCCE... 这是一个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()

Results in: 结果是:

# spoons starting...

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

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

Questions: 问题:

  • Why does it say 0 tests ? 为什么说0 tests
  • Why are blep and blap (start and end of run) not printed? 为什么不打印blepblap (开始和结束运行)?

On a more general note: 更一般地说:

  1. Can someone possibly point to a good tutorial/book explaining "proper use"/"good practice" when it comes to TestResult, TestRunner, TestLoader, etc. I got "TDD with Python", but it doesn't seem to explain any of this. 当涉及到TestResult,TestRunner,TestLoader等时,有人可能会指出一本很好的教程/书籍解释“正确使用”/“良好实践”。我得到了“TDD with Python”,但它似乎没有解释任何这个。

  2. Can someone possibly tell me why unittest2 often seems to be used instead of unittest? 有人可能会告诉我为什么通常会使用unittest2而不是unittest?

addendum 附录

Following Omar Diab's efforts at looking at the source code I tried this: 在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')

Unfortunately each test_XXX method then gave: 不幸的是,每个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

Wow, no responses. 哇,没有回复。 I'm surprised. 我很惊讶。

This is a hack which most people could no doubt work out for themselves, if you want stuff to happen at the start of the run and end of the run: 如果您希望在运行开始和运行结束时发生事情,那么大多数人无疑可以自行解决这个问题:

Subclass TestCase, as per: 子类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

Then make all your TestCases subclass from this one... 然后从这一个中创建所有TestCases子类......

The point being, if you want this to happen, that your app is only constructed once. 关键是,如果您希望这种情况发生,您的应用程序只构建一次。 Handling the responsibility of ensuring that it is "pristine" for each successive setUp is up to you of course. 处理确保每个连续setUp “原始”的责任当然取决于你。 Obviously you could use setUpClass instead but then you don't have access to the TestCase instance. 显然你可以使用setUpClass但是你无法访问TestCase实例。

I am having the same problem, so I took a look at the source code. 我遇到了同样的问题,所以我看了一下源代码。

Inspecting unittest.TextTestRunner and unittest.TestCase , it looks like startTestRun() and stopTestRun() get called manually. 检查unittest.TextTestRunnerunittest.TestCase ,看起来像手动调用startTestRun()stopTestRun() In unittest.TextTestRunner , it works like so: unittest.TextTestRunner ,它的工作原理如下:

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

and in your case, unittest.TestCase , it is like so: 在你的情况下, 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()
    # ...

So it looks like startTestRun only actually gets called by TestCase.run() if you don't pass in result . 所以看起来startTestRun实际上只有在你没有传入result时才被TestCase.run()调用。 You're passing in result , so it's not happening. 你传递了result ,所以它没有发生。

This seems like a bug to me! 这对我来说似乎是个错误! But basically it means you can extend TestCase or TestSuite , reimplement the run method, and then call those methods by hand; 但基本上它意味着你可以扩展TestCaseTestSuite ,重新实现run方法,然后手动调用这些方法; or just call them outside of those respective run methods. 或者只是在那些相应的run方法之外调用它们。

Hope this helps! 希望这可以帮助!

Think the creation of the TestResult object in TestCase.run() is misunderstood as no access to stream, descriptions, verbosity. 认为在TestCase.run()创建TestResult对象被误解为无法访问流,描述,详细程度。 provide as KWarg it works 作为KWarg提供它的工作原理

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM