我想测量每个测试用例运行所需的(墙?)时间。
我想在一个timeit中包装test_runner会完成这项工作,但在我潜入那个兔子洞之前,也许还有一种更聪明的方法可以做到这一点?
这已经给了我一个cProfile来弥补,但没有什么真正跳出来的可怕的糟糕。我想也许我的时间可以集中在那些运行时间最长的那些。
time python -m cProfile -o keep-p4-serialize.profile manage.py test -v 3 -k --parallel 4
例如:
test_dependencies (api.tests.TestMetricClasses) ... ok (4.003s)
test_metrics (api.tests.TestMetricClasses) ... ok (8.329s)
test_parameters (api.tests.TestMetricClasses) ... ok (0.001s)
答案 0 :(得分:4)
这足以让我(相对时间),但它并不适用于并行运行的测试,并且肯定有提高时间准确性的余地。尽管如此:
通过settings.py
覆盖默认参赛者:
TEST_RUNNER = 'myapp.test_runner.MyTestRunner'
从而创建自己的test_runner myapp/test_runner.py
:
from django.test.runner import DiscoverRunner
class MyTestRunner(DiscoverRunner):
test_runner = TimedTextTestRunner
反过来,覆盖结果类:
from unittest.runner import TextTestRunner, TextTestResult
class TimedTextTestRunner(TextTestRunner):
resultclass = TimedTextTestResult
现在结果对象不只是一个结果而是很多,所以我们需要一组时钟,通过测试键入。然后捕获测试开始的时间并打印出打印成功字符串时经过的时间:
class TimedTextTestResult(TextTestResult):
def __init__(self, *args, **kwargs):
super(TimedTextTestResult, self).__init__(*args, **kwargs)
self.clocks = dict()
def startTest(self, test):
self.clocks[test] = time()
super(TextTestResult, self).startTest(test)
if self.showAll:
self.stream.write(self.getDescription(test))
self.stream.write(" ... ")
self.stream.flush()
def addSuccess(self, test):
super(TextTestResult, self).addSuccess(test)
if self.showAll:
self.stream.writeln("ok-dokey (%.6fs)" % (time() - self.clocks[test]))
elif self.dots:
self.stream.write('.')
self.stream.flush()
这给了我看起来像这样的测试报告:
test_price_impact (api.tests.TestGroupViews) ... ok-dokey (3.123600s)
test_realised_spread (api.tests.TestGroupViews) ... ok-dokey (6.894571s)
test_sqrt_trade_value (api.tests.TestGroupViews) ... ok-dokey (0.147969s)
test_trade_count_share (api.tests.TestGroupViews) ... ok-dokey (3.124844s)
test_trade_size (api.tests.TestGroupViews) ... ok-dokey (3.134234s)
test_value_share (api.tests.TestGroupViews) ... ok-dokey (2.939364s)
答案 1 :(得分:2)
nose有一个计时器插件,它记录每次单个测试执行的挂起时间。
https://github.com/mahmoudimus/nose-timer/tree/master/nosetimer
Nose的coberatura xml报告还默认显示每次测试所花费的时间。
对于django特定问题,可以通过一些简单的优化来增加测试的运行时间:
test_dependencies
和test_metrics
中有多少项测试?它们中有哪些类型的测试?
答案 2 :(得分:0)
一个老问题,但我碰到它,发现没有提到django-slowtest
,我认为这绝对值得一提。我已经使用了很长一段时间了,我对结果非常满意。唯一的缺点是,它尚未声明它正式支持Django> = 2 ,但是我没有遇到任何问题,并且由于它仅在我身上开发,因此我可以放心使用它。
--parallel
上正常工作slow
时可以在阈值中配置https://github.com/realpython/django-slow-tests
来自文档: 安装:
$ pip install django-slowtests
添加以下设置:
TEST_RUNNER = 'django_slowtests.testrunner.DiscoverSlowestTestsRunner'
NUM_SLOW_TESTS = 10
# (Optional)
SLOW_TEST_THRESHOLD_MS = 200 # Only show tests slower than 200ms
# (Optional)
ALWAYS_GENERATE_SLOW_REPORT = False # Generate report only when requested using --slowreport flag
最后,运行测试
$ 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)