【问题标题】:How to know time spent on each test when using unittest?使用unittest时如何知道每个测试花费的时间?
【发布时间】:2012-02-29 16:05:54
【问题描述】:

Unittest 仅显示运行所有测试所花费的总时间,但不单独显示每个测试所花费的时间。

使用unittest时如何添加每个测试的计时?

【问题讨论】:

    标签: python performance unit-testing


    【解决方案1】:

    我想,现在不可能:http://bugs.python.org/issue4080

    但是你可以这样做:

    import unittest
    import time
    
    class SomeTest(unittest.TestCase):
        def setUp(self):
            self.startTime = time.time()
    
        def tearDown(self):
            t = time.time() - self.startTime
            print('%s: %.3f' % (self.id(), t))
    
        def testOne(self):
            time.sleep(1)
            self.assertEqual(int('42'), 42)
    
        def testTwo(self):
            time.sleep(2)
            self.assertEqual(str(42), '42')
    
    if __name__ == '__main__':
        suite = unittest.TestLoader().loadTestsFromTestCase(SomeTest)
        unittest.TextTestRunner(verbosity=0).run(suite)
    

    结果:

    __main__.SomeTest.testOne: 1.001
    __main__.SomeTest.testTwo: 2.002
    ----------------------------------------------------------------------
    Ran 2 tests in 3.003s
    
    OK
    

    【讨论】:

    • 我想在一些基类中定义它会很好,这样人们就可以很容易地把它混进去。
    • 绝对是。这只是一种可能性的示例。
    • 感谢您的回答。你能解释一下为什么在每个测试用例的开头都有 sleep 方法吗?
    • 你能否解释一下为什么它在每个测试用例中都是增量的?
    【解决方案2】:

    您可以将pytest--durations=0 一起使用,它会为您提供每次测试的执行时间

    【讨论】:

      【解决方案3】:

      Nose 使用 pinnochio extension 进行测试有一个 stopwatch 选项,如果你可以选择鼻子,它会给你这个。

      它还有很多其他有用的功能和插件可以让使用 unittest 更好。

      【讨论】:

      • Nose 没有积极维护,建议迁移到 pytest
      【解决方案4】:

      这里是 horejsek 回答的脚本变体。 它将猴子补丁 django TestCase 以便每个 TestCase 都会给出它的总运行时间。

      您可以将此 sript 放置在您的 settings.py 所在的根包的 __init__.py 中。 之后,您可以使用 ./mange.py test -s

      运行测试
      from django import test
      import time
      
      
      @classmethod
      def setUpClass(cls):
          cls.startTime = time.time()
      
      
      @classmethod
      def tearDownClass(cls):
          print "\n%s.%s: %.3f" % (cls.__module__, cls.__name__, time.time() - cls.startTime)
      
      
      test.TestCase.setUpClass = setUpClass
      test.TestCase.tearDownClass = tearDownClass
      

      【讨论】:

        【解决方案5】:

        仅使用命令行的解决方案:

        1/ 安装nose(流行的替代测试运行器)和扩展pinocchio

        $ pip install nose pinocchio
        

        2/ 运行测试并记录时间(时间保存在文件.nose-stopwatch-times中)

        $ nosetests --with-stopwatch
        

        3/ 显示按时间递减排序的测试名称:

        $ python -c "import pickle,operator,signal; signal.signal(signal.SIGPIPE, signal.SIG_DFL); print '\n'.join(['%.03fs: %s'%(v[1],v[0]) for v in sorted(pickle.load(open('.nose-stopwatch-times','r')).items(), key=operator.itemgetter(1), reverse=True)])" | less
        

        【讨论】:

        • 鼻子已经过去几年了。每个人都使用 py.test,这是正确的。
        • 我认为当它应该打印s时打印ms
        • 注意pinnochio 错字:应该是pinocchio
        【解决方案6】:

        您可以使用django-slowtests,它提供如下输出:

        $ python manage.py test
        Creating test database for alias 'default'...
        ..........
        ----------------------------------------------------------------------
        Ran 10 tests in 0.413s
        
        OK
        Destroying test database for alias 'default'...
        
        Ten slowest tests:
        0.3597s test_detail_view_with_a_future_poll (polls.tests.PollIndexDetailTests)
        0.0284s test_detail_view_with_a_past_poll (polls.tests.PollIndexDetailTests)
        0.0068s test_index_view_with_a_future_poll (polls.tests.PollViewTests)
        0.0047s test_index_view_with_a_past_poll (polls.tests.PollViewTests)
        0.0045s test_index_view_with_two_past_polls (polls.tests.PollViewTests)
        0.0041s test_index_view_with_future_poll_and_past_poll (polls.tests.PollViewTests)
        0.0036s test_index_view_with_no_polls (polls.tests.PollViewTests)
        0.0003s test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
        0.0002s test_was_published_recently_with_recent_poll (polls.tests.PollMethodTests)
        0.0002s test_was_published_recently_with_old_poll (polls.tests.PollMethodTests)
        

        如果您查看django_slowtests/test_runner.py,您也可以自己调整该技术。

        【讨论】:

          【解决方案7】:

          PyCharm CE (free) 提供了unittest 持续时间的清晰视图。它还有助于按目录结构和文件进行聚合,并允许您按持续时间排序:

          正如@horejsek 所提到的,unittest 在使用开放 PR 添加持续时间测量时存在问题:https://github.com/python/cpython/pull/12271

          【讨论】:

            【解决方案8】:

            我订阅了所有其他用户的答案,但他们大多有一个小问题。

            其实用time.perf_counter()代替time.time()更准确

            def perf_time():
                start = time.perf_counter()
                time.sleep(1)
                end = time.perf_counter()
                print(end - start)
            
            def time_time():
                start = time.time()
                time.sleep(1)
                end = time.time()
                print(end - start)
            
            
            >>> time_time()
            1.0010485649108887
            >>> perf_time()
            1.0010385409987066
            

            这里的差异很小,但有时这真的很重要。

            我也可以为这个主题分享一个不错的装饰器:

            def time_func(func):
                def wrapper(*args, **kwargs):
                    start = time.perf_counter()
                    result = func(*args, **kwargs)
                    end = time.perf_counter()
                    print(f"{func.__name__}: {end - start:.3}s")
                    return result
                return wrapper
            
            
            class TestCase(unittest.TestCase):
            
                @time_func
                def test_case(self):
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-10-08
              • 1970-01-01
              • 2021-12-13
              • 1970-01-01
              • 2013-07-13
              • 2017-03-05
              • 2015-01-01
              相关资源
              最近更新 更多