如何使用模拟返回无参数来解析已知的参数?

时间:2019-03-20 23:32:13

标签: python-3.x unit-testing mocking argparse python-unittest

下面,我有一个基于命令行输入返回两个日期的函数。如何使用模拟使它能够对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()

1 个答案:

答案 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,则它将解析常规命令行。但是您可以提供生成所需的argsextras的任何字符串列表。实际上,您可以模拟命令行。

另一个选择是定义一个args命名空间对象,例如。 args = argparse.Namespace(start_dt=None, end_dt='foobar')。然后,您可以像以前一样使用args.start_dt

使测试更容易的另一件事是使parser仅在代码作为脚本运行时才运行,而不是在导入时才运行。也就是说,将其放在“如果 name ==' main ”:块中。