Тестирование функции на основе стороннего сервиса - PullRequest
0 голосов
/ 20 марта 2019

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

Предположим, что функция выглядит следующим образом:

def sync_check():
    delta_secs = 90
    now = datetime.datetime.now().utcnow()
    res = requests.get('<url>')
    alert = SlackAlert()
    last_value = res[-1]['date'] # Last element of the array is the most recent
    secs = (now - last_value).seconds

    if secs >= delta_secs:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
    else:
        alert.notify('in sync')

Как лучше написать модульный тест для этой функции?Мне нужно протестировать ветки if и else, но это зависит от стороннего сервиса.

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

if test:
    url = <mock_web_server_url>
else:
    url = <third_party_service_url>

Более того, модульное тестирование вызовет оповещения об ослаблении, что не должно происходить.

Так что я должен снова изменить кодовую базукак:

if secs >= delta_secs:
    if test:
        logging.debug("out of sync alert sent - testing mode")
    else:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
else:
    if test:
        logging.debug("in sync alert sent - testing mode")
    else:
        alert.notify('in sync')

Что мне не очень нравится.

Мне не хватает какого-либо дизайна для решения этой проблемы?

1 Ответ

0 голосов
/ 20 марта 2019

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

Ваш код в конечном итоге будет выглядеть примерно так:

def sync_check(alert):
    delta_secs = 90
    now = datetime.datetime.now().utcnow()
    res = requests.get('<url>')
    last_value = res[-1]['date'] # Last element of the array is the most recent
    secs = (now - last_value).seconds

    if secs >= delta_secs:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
    else:
        alert.notify('in sync')

, и в тестовом случае объект оповещения может быть таким простым:

class TestAlert:
    def __init__(self):
        self.message = None

    def notify(self, message):
        self.message = message

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

def test_sync_check():
    alert = TestAlert()
    sync_check(alert)
    assert alert.message == 'in sync'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...