下面,我有一个基于命令行输入返回两个日期的函数。如何使用模拟使它能够对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()
来使它运行,以便在单元测试的此部分运行时,get_the_args()
函数的args输出返回None?我需要更改我的ockock.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()
答案 0 :(得分: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
仅在代码作为脚本运行时才运行,而不是在导入时才运行。也就是说,将其放在“如果 name ==' main ”:块中。