#python-3.x #unit-testing #mocking #argparse #python-unittest
#python-3.x #модульное тестирование #издевательство #argparse #python-unittest
Вопрос:
Ниже у меня есть функция, которая возвращает две даты на основе ввода из командной строки. Как я могу использовать mock, чтобы сделать так, чтобы я мог выполнять модульное тестирование в инструкции else?
# time from of pull
def time_frame():
"""
checks for optional user input for start and end date of data pull
creates start and end date for query
:return: start and end date
"""
# get the dates
args, leftovers = get_the_args()
if args.start_dt is not None and args.end_dt is not None:
return args.start_dt, args.end_dt
else:
# get today
the_today_start_date, the_today_end_date = get_dates_from_today()
return the_today_start_date, the_today_end_date
Я попытался с помощью mock_get_the_args.return_value = mock.Mock(return_value=None), mock.Mock()
сделать так, чтобы вывод args get_the_args()
функции возвращал None при выполнении этого раздела моего модульного теста? Что мне нужно, чтобы изменить мой макет.Mock() представляет args
переменную для этой работы?
Ниже приведен модульный тест на данный момент:
# the time frame
@mock.patch('src.toolkit.get_dates_from_today')
@mock.patch('src.toolkit.get_the_args')
def test_time_frame(mock_get_the_args, mock_get_dates_from_today):
# set some dates
start_date = '2019-01-01'
end_date = '2019-01-01'
# mocking
mock_get_the_args.return_value = mock.Mock(), mock.Mock()
mock_get_dates_from_today.return_value = mock.Mock(), mock.Mock()
start_date, end_date = time_frame()
mock_get_the_args.assert_called_once()
mock_get_the_args.return_value = mock.Mock(return_value=None), mock.Mock()
start_date, end_date = time_frame()
mock_get_dates_from_today.assert_called_once()
Ответ №1:
Модульное тестирование с argparse
кодом немного сложно, потому что обычно оно ожидает ввода из командной строки. Но само тестирование использует командную строку (возможно, с помощью собственного анализатора argparse).
Я предполагаю, что get_the_args
настраивает анализатор и возвращает parser.parse_known_args()
.
В целях тестирования удобно предоставить себе возможность предоставления явного argv
списка.
например:
def time_frame(argv=None):
"""
checks for optional user input for start and end date of data pull
creates start and end date for query
:return: start and end date
"""
# get the dates
args, leftovers = get_the_args(argv)
...
где get_the_args
используется parse_known_args(argv)
.
Если argv
равно None, то выполняется синтаксический анализ обычной командной строки. Но вы можете предоставить любой список строк, который генерирует желаемые args
и extras
. По сути, вы можете имитировать командную строку.
Другой вариант — определить args
объект пространства имен, например. args = argparse.Namespace(start_dt=None, end_dt='foobar')
. Затем вы можете использовать args.start_dt
, как и раньше.
Еще одна вещь, которая упрощает тестирование, — это сделать parser
запускаемым только тогда, когда код выполняется как скрипт, а не когда он импортирован. То есть поместите это в `if name ==’main‘: block.