Как издеваться над внешними серверами в модульных тестах Python?
У меня есть несколько модульных тестов, которые занимают много времени (минуты) из-за вызовов внешних служб (Twitter, Facebook, Klout и т.д.).
Я хотел бы кэшировать результаты этих сервисов и показывать их прозрачно, с минимальными изменениями в моих текущих тестах. Кэш-ключ зависит от URL, аргументов запроса, заголовков и т.д., Поэтому он довольно сложный.
Какой лучший способ сделать это?
Ответы
Ответ 1
Вы бы (должны) обычно использовали какой-то адаптер для подключения к этим внешним службам, модулям. Это ваши интерфейсы для внешнего мира и могут быть mock ed и поддельные ответы, созданные в зависимости от сценария.
Я экспериментировал с несколькими насмешливыми библиотеками и, наконец, нашел Mock, чтобы быть наиболее подходящим для меня.
Ответ 2
Вот код. Мы используем библиотеку запросов для вызова внешних API. Поэтому мы создаем контекстный процессор с объектом mock запросов.
Итак, если бы мы тестировали функцию get_data, это было бы тем, как мы будем обманывать запрос внешнему API:
import requests
import mock
import unittest
def get_data(url):
resp = requests.get(url)
return resp
class GetDataTest(unittest.TestCase):
def test_get_data(self):
with mock.patch.object(requests, 'get') as get_mock:
get_mock.return_value = mock_response = mock.Mock()
mock_response.status_code = 200
mock_response.content = {'twitter_handle': '@twitter'}
resp = get_data("http://this_address_does_not_exist.com")
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.content['twitter_handle'], '@twitter')
Ответ 3
Технически, если он использует внешние службы, это не unit test, а тест интеграции. Для unit test и ускорьте свой тестовый код, используя mock-объекты. Здесь вы можете найти информацию о mock-объектах python:
http://python-mock.sourceforge.net/