Python 3 unittest имитирует пользовательский ввод - PullRequest
4 голосов
/ 25 августа 2009

Как я могу имитировать пользовательский ввод в середине функции, вызываемой модульным тестом (используя unittest в Python 3)? Например, у меня есть функция foo(), вывод которой я тестирую. В функции foo() запрашивается ввод пользователя:

x = input(msg)

А вывод основан на вводе:

print("input: {0}".format(x))

Я бы хотел, чтобы мой модульный тест запустился foo(), введите вход и сравните результат с ожидаемым результатом.

Ответы [ 3 ]

8 голосов
/ 25 августа 2009

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

def my_test_input(message):
  return 7

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

def my_test_input(retval, message):
  return retval

и затем вы вставите частичную функцию в input:

import functools
test_input_a = functools.partial(my_test_input, retval=7)
test_input_b = functools.partial(my_test_input, retval="Foo")

Оставляя test_input_a и test_input_b в качестве функций, которые принимают один аргумент message с уже связанным аргументом retval.

3 голосов
/ 25 августа 2009

Трудности в тестировании какого-либо компонента из-за зависимостей - это обычно признак плохого дизайна. Ваша функция foo должна зависеть не от глобальной функции input, а от параметра. Затем, когда вы запускаете программу в производственной среде, вы связываете все так, что вызывается foo с результатом, который возвращает input. Так что foo следует читать:

def foo(input):
    # do something with input

Это значительно упростит тестирование. И, кстати, если у ваших тестов есть IO зависимости, то это уже не модульные тесты, а скорее функциональные. Загляните в блог Misko Hevery , чтобы узнать больше о тестировании.

1 голос
/ 10 августа 2018

Я думаю, что лучший подход - обернуть функцию input в пользовательскую функцию и высмеивать последнюю. Точно так же, как описано здесь: Необработанный ввод Python в юнит-тестах

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