Python: Продвинутое тестирование
Теория: Манкипатчинг
В предыдущем уроке мы тестировали гипотетическую функцию get_private_fork_names(username), применяя инверсию зависимостей.
Вспомним содержимое этой функции в ее исходном виде:
В некоторых ситуациях инверсия зависимостей подходит идеально. В других случаях из-за нее код становится сложнее и запутаннее, особенно если зависимости требуются глубоко в стеке вызовов — придется пробрасывать зависимость через все промежуточные функции.
В примере выше, функция process_order() использует функцию нотификации, которая уже использует мешающий тестам почтовый клиент. Если мы попробуем применить инверсию зависисмостей, то придется пробрасывать клиент во все функции, даже те, что не испозьзуют его непосредственно:
Но есть способ, который позволяет добраться до нужных вызовов и изменить их даже без инверсии зависимостей. Именно его мы изучим в этом уроке.
Манкипатчинг
Python позволяет подменять модули, классы и методы прямо во время работы программы из любого ее места:
Этой возможностью мы можем воспользоваться и в тестах, подменив проблемный, недетерминированный метод:
Так происходит изменение модулей и классов прямо во время работы программы — в рантайме. Этот процесс называется манкипатчингом (monkey patching). Он считается опасной практикой при написании обычного кода в Python, ведь после манкипатчинга объект изменяет свое поведение не только в этом модуле, но и вообще по всей программе. Но он очень популярен и удобен в библиотеках или во время тестирования.
Для упрощения работы Pytest предоставляет специальную фикстуру monkeypatch. Она позволяет указать конктретный метод класса или модуля, что нужно заменить. После выполнения теста, все изменения будут отменены, и так манкипатчинг в тестах не повлияет на всю программу.
Патчинг запросов
Еще один частый пример использования манкипатчинга - подмена самого HTTP-запроса. Как пример, библиотека pook. С ее помощью подменяются запросы без прямого взаимодействия с HTTP-клиентом, как в случае инверсии зависимостей:
Подобные библиотеки для патчинга запросов работают несколько хитрее - они заменяют методы стандартной, низкоуровневой библиотеки для работы с запросами. Так в Python это библиотека urllib3. Все остальные популярные высокоуровневые библиотки, как requests внутри используют urllib3.
Рассмотрим пример использования:
Вызов pook.get(url) задает полный адрес страницы, запрос к которой надо перехватить. Pook анализирует все выполняемые запросы и подменяет только тот, который соответствует этим параметрам.
Параметры reply и response_json описывают ответ, который нужно вернуть по данному запросу. В самом простом случае достаточно указать код возврата. В нашей ситуации нужен не только код, но и данные. Именно на этих данных мы и проверяем работу функции get_private_fork_names().
Кассеты
Еще одно из применений манкипатчинга - кассеты. Так называются библиотеки, что сочетают в себе манкипатчинг запросов и использование тестовых данных:
При первом запуске тестов выполнится настоящий запрос. Библиотека запишет его результаты в тестовые данные, например по пути tests/cassettes/ в удобном формате, чаще yml или JSON.
В последущие разы, библиотека подменит запрос и в качестве ответа вернет записанную кассету. Кассеты удобны тем, что генерация данных лежит полностью на библиотеке. Также что записанные данные полностью соотвествуют ответу нужного нам сайта или сервиса. Нам же нужно всего одни раз выполнить настоящий запрос. В дополнение, так как данные сохранены в текстовом формате, мы можем редактировать их, инсценируя ситуации разных ответов от сервиса.
Заключение
В чем плюсы и минусы такого способа работы?
Главный плюс манкипатчинга в том, что такой способ тестирования практически универсальный. Его можно использовать с любым кодом, причем без необходимости править сам код. Программа даже не будет догадываться, что ее тестируют.
Минус же заключается в том, что оптимальным подходом в тестировании считается тестирование «черным ящиком». Подход, при котором мы не знаем об внутреннем устройстве программы, а тестируем лишь исходя из входных и ожидаемых выходных данных. С манкипатчингом, тестирование превращается в тестирование «прозрачным ящиком». Это значит, что тест знает про устройство тестируемого кода и зависит от внутренностей. Это делает тесты хрупкими. Функция может измениться без потери работоспособности, но тесты придется переписывать, потому что они завязаны на конкретные методы и атрибуты.
Рекомендуемые программы
Завершено
0 / 8




