Для данного объекта, как получить список связанных методов, которые вызываются во время выполнения

Вопрос исходит из этого сценария:

Мы создали фреймворк для тестирования apis нашего проекта в северном направлении на основе pytest. И теперь мы хотим получить отчет о покрытии того, сколько apis протестировано (в основном, вызвано), запустив тестовые скрипты, которые у нас есть.

У нас уже есть четко определенный клиентский менеджер, который превращает каждый API в метод Python. Например, скажем, у нас есть API GET /userтогда у нас будет метод get_user который отправляет фактический запрос на сервер.

Сейчас мы используем покрытие python (фактически pytest-cov, но это то же самое), которое даст нам отчет о покрытии кода, и на основании этого у нас будет какое-то представление о том, сколько вызывается apis. Тем не менее, это не совсем точно и ясно.

Поэтому ключевой вопрос заключается в том, есть ли способ получить список связанных методов, которые вызываются во время выполнения.

Я хотел бы привести пример для иллюстрации вопроса.

class Client(object):
    def __init__(self):
        pass

    def get_user(self, user):
        pass

    def post_user(self, user):
        pass

    def delete_user(self, user):
        pass

def test_get_user():
    Client().get_user("user")

def test_post_user():
    Client().post_user("user")

После выполнения двух тестов, как я могу получить отчет о том, что get_user а также post_user был вызван и delete_user не был вызван во время последнего запуска.

Одно из возможных решений заключается в том, что, поскольку запуск тестов с cover.py даст нам достаточно информации о номерах строк и выполняемых файлах, возможно, я смогу проанализировать то, что мне нужно оттуда.

Другое возможное решение - отследить, какой метод вызывается в Client Я определил. На самом деле я решил мой вопрос в моем конкретном случае, когда все методы API будут вызывать общий метод, в моем случае, call_api, я использую inspect в методе call_apiи я могу получить имя метода, потому что говорят get_user всегда вызывающий call_api, Однако это решение работает только для этого особого случая и не является общим решением.

Я также посмотрел на модуль trace, это выглядит близко к тому, что я хочу, но, к сожалению, вы должны использовать tracer(Trace instance) запустить команду или функцию.

Что я хочу достичь в конечном итоге это:

tracer = Trace(obj_to_trace)
tracer.start_trace()
# using obj_to_trace 
tracer.end_trace()
tracer.get_called_methods()

2 ответа

Coverage.py не имеет этой функции. Вам нужно будет использовать trace модуль или постобработка результатов покрытия, чтобы получить имена методов.

Я не знаю, можете ли вы получить это из самой библиотеки покрытия, но вы определенно можете получить эту информацию, обрабатывая файлы самостоятельно.

Посмотрите на модуль AST. Это позволяет вам анализировать все файлы, о которых сообщалось по покрытию, и генерировать диапазоны строк для каждой функции. Оттуда вам просто нужно проверить, какие функции выполняли какие-либо строки вообще.

Но... поскольку покрытие должно делать что-то похожее, может быть проще просто изменить покрытие, чтобы вместо этого сообщать о локальной функции.

Другие вопросы по тегам