如何衡量每个django测试的时间曲线?

Joh*_*Mee 7 django profiling unit-testing

我想测量每个测试用例运行所需的(墙?)时间.

我想在一个timeit中包装test_runner可以完成这项工作,但在我潜入那个兔子洞之前,或许还有更聪明的方法吗?

这已经给了我一个cProfile毛孔,但没有什么真的跳出来可怕的坏.我想也许我的时间可以集中在运行时间最长的那些上.

time python -m cProfile -o keep-p4-serialize.profile manage.py test -v 3 -k --parallel 4
Run Code Online (Sandbox Code Playgroud)

例如:

test_dependencies (api.tests.TestMetricClasses) ... ok (4.003s)
test_metrics (api.tests.TestMetricClasses) ... ok (8.329s)
test_parameters (api.tests.TestMetricClasses) ... ok (0.001s)
Run Code Online (Sandbox Code Playgroud)

Joh*_*Mee 6

这足以让我通过(相对时间),但它不适用于并行运行的测试,并且肯定有提高时间准确性的空间。尽管如此:

通过settings.py以下方式覆盖默认运行程序:

TEST_RUNNER = 'myapp.test_runner.MyTestRunner'
Run Code Online (Sandbox Code Playgroud)

然后创建你自己的 test_runner myapp/test_runner.py

from django.test.runner import DiscoverRunner

class MyTestRunner(DiscoverRunner):
    test_runner = TimedTextTestRunner
Run Code Online (Sandbox Code Playgroud)

并且,反过来,重写结果类:

from unittest.runner import TextTestRunner, TextTestResult

class TimedTextTestRunner(TextTestRunner):
    resultclass = TimedTextTestResult
Run Code Online (Sandbox Code Playgroud)

现在结果对象不仅仅是一个结果,而是多个结果,所以我们需要一组时钟,由测试键控。然后捕获测试开始的时间并打印出打印成功字符串时经过的时间:

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()
Run Code Online (Sandbox Code Playgroud)

这给了我这样的测试报告:

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)
Run Code Online (Sandbox Code Playgroud)


Nrz*_*ine 6

更新:
原帖是在 2019 年,似乎下面讨论的包 ( django-slowtest) 不再维护。至于现在我也没有看到任何维护的叉子。

——

老问题,但我遇到了它并注意到django-slowtest没有提到,我认为这绝对值得一提。我已经使用它一段时间了,我对结果非常满意。唯一的缺点是,它还没有正式声明它支持 Django >= 2 ,但我没有遇到任何问题,因为它只为我开发,所以我觉得使用它很安全。

  • 正常工作 --parallel
  • 可配置在运行测试后要显示多少慢测试
  • 当它应该将测试标记为 slow
  • 具有报告(导出)功能。
  • 仍维持至 2019-02

https://github.com/realpython/django-slow-tests

来自文档:安装:

$ pip install django-slowtests
Run Code Online (Sandbox Code Playgroud)

添加以下设置:

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
Run Code Online (Sandbox Code Playgroud)

最后,运行你的测试

$ 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)
Run Code Online (Sandbox Code Playgroud)


dm0*_*514 3

鼻子有一个计时器插件,它记录每个测试执行的墙时间。

https://github.com/mahmoudimus/nose-timer/tree/master/nosetimer

默认情况下,Nose 的 coberatura xml 报告还显示每次测试所花费的时间。


对于 django 的特定问题,可以进行许多简单的优化来增加测试的运行时间:

  • 如果您不使用数据库特定功能,请使用 Sqlite
  • 使用 md5 密码哈希器(或根本不使用密码哈希器)
  • 禁用迁移
  • 删除 io,尽可能隔离逻辑,以避免创建复杂的模型依赖项

test_dependencies和中有多少个测试test_metrics?其中有哪些类型的测试?