Получите обзор SQL количества запросов для каждого теста в наборе тестов - PullRequest
3 голосов
/ 24 апреля 2020

У меня есть большое Django приложение с тоннами тестов, которым требуется SQL оптимизация запросов.

Я использую pytest- django для запуска своих тестов.

I не хочу добавлять assertNumQueries или django-assert-num-queries для каждого теста в отдельности, а вместо этого создать обзор о том, сколько SQL запросов выполняет каждый из всех тестов, чтобы узнать, какой код требуется наибольшая оптимизация, например:

test                         | number of queries
------------------------------------------------
test_a.py::test_my_function1 |  5
test_a.py::test_my_function3 |  2
test_a.py::test_my_function5 |  7

Возможно ли настроить ловушку pytest в conftest.py, который подсчитывает количество SQL запросов для каждого теста (БД) и показывает их в результате - без необходимости изменять источник моих тестов (например, добавление декораторов)?

Мой наивный подход состоял бы в том, чтобы использовать эти ловушки и каким-то образом получать доступ к соединению с базой данных до и после каждого теста:

def pytest_runtest_call(item):
    pass

def pytest_runtest_teardown(item, nextitem):
    return True

1 Ответ

1 голос
/ 25 апреля 2020

Для записи количества запросов достаточно приспособления autouse. В приведенном ниже примере я сохраняю счет в queries_count dict под объектом конфигурации:

@pytest.fixture(autouse=True)
def record_query_count(request):
    from django.test.utils import CaptureQueriesContext
    from django.db import connection

    with CaptureQueriesContext(connection) as context:
        yield
    num_performed = len(context)

    if not hasattr(request.config, "query_counts"):
        request.config.query_counts = dict()
    request.config.query_counts[request.node.nodeid] = num_performed

Чтобы вывести результаты, я добавляю пользовательский раздел в пользовательском имплисе pytest_terminal_summary крючок. Поместите следующий код в файл с именем conftest.py в проекте или тестах root dir:

import os

def pytest_terminal_summary(terminalreporter, exitstatus, config):
    content = os.linesep.join(
        f'{nodeid:40} | {num_queries}'
        for nodeid, num_queries in config.query_counts.items()
    )
    terminalreporter.ensure_newline()
    terminalreporter.section('number of queries', sep='-', bold=True)
    terminalreporter.line(content)

Запуск тестов теперь даст:

tests/test_db.py ...                                                                [100%]

----------------------------------- number of queries ------------------------------------
tests/test_db.py::test_add_entry      | 2
tests/test_db.py::test_remove_entry   | 2
tests/test_db.py::test_no_entries     | 1
=================================== 3 passed in 0.26s ====================================
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...