Python 3.x 使用多个输入调用对函数进行单元测试的效率如何?

Python 3.x 使用多个输入调用对函数进行单元测试的效率如何?,python-3.x,unit-testing,input,mocking,pytest,Python 3.x,Unit Testing,Input,Mocking,Pytest,我有一个按预期工作的单元测试,但是我觉得这不是用pytest测试多个输入的最佳方法。这绝对违反了干燥原则。我想有更好的办法,但我不知道怎么办。我也不知道该如何处理这个mock。它没有使用,但必须存在(请参阅下面代码中函数中的“mock_choice”参数) 我想通过电话循环可能会奏效,但这并没有达到预期的效果。我真的想不出除了使用副作用和打四次电话测试以确保得到预期的返回值之外的其他方法 要测试的功能 def export_options(): while True: t

我有一个按预期工作的单元测试,但是我觉得这不是用pytest测试多个输入的最佳方法。这绝对违反了干燥原则。我想有更好的办法,但我不知道怎么办。我也不知道该如何处理这个mock。它没有使用,但必须存在(请参阅下面代码中函数中的“mock_choice”参数)

我想通过电话循环可能会奏效,但这并没有达到预期的效果。我真的想不出除了使用副作用和打四次电话测试以确保得到预期的返回值之外的其他方法

要测试的功能

def export_options():
    while True:
        try:
            choice = int(input("\nPlease make a selection"))
            if choice in ([option for option in range(1, 5)]):
                return choice  # This what I'm testing
            else:
                print("\nNot a valid selection\n")
        except ValueError as err:
            print("Please enter an integer")
测试功能

@mock.patch('realestate.app.user_inputs.input', side_effect=[1, 2, 3, 4])
def test_export_options_valid_choice(mock_choice): # mock_choice needs to be here but isn't used!

    export_option = user_inputs.export_options()
    assert export_option == 1

    export_option = user_inputs.export_options()
    assert export_option == 2

    export_option = user_inputs.export_options()
    assert export_option == 3

    export_option = user_inputs.export_options()
    assert export_option == 4

测试有效。它在函数返回1到4之间的所有值时传递。但是,由于代码非常重复,我想知道是否有更好的方法来测试多个输入调用,因为我想在将来的测试中应用相同的方法。

您可以使用for循环来避免重复代码

@mock.patch('realestate.app.user_inputs.input')
def test_export_options_valid_choice(self, mock_choice):
    for response in [1, 2, 3, 4]:
        with self.subTest(response=response)
            mock_choice.return_value = response
            export_option = user_inputs.export_options()
            self.assertEqual(export_option, response)
            # Not in original version, but other tests might need it.
            mock_choice.assert_called_once_with("\nPlease make a selection")
            mock_choice.reset_mock()
将告诉您哪些输入失败


这样做的唯一方法是使用unittest模块进行子测试吗?我知道pytest不支持子测试,但我希望有类似类型的黑客

您当然可以在不使用子测试的情况下进行循环,但您可能很难判断哪个输入失败。更一般地说,您可以为每个测试调用公共辅助函数,而不是循环

特别是对于pytest,您可以使用
@pytest.mark.parametrize
装饰程序来自动执行此操作

@pytest.mark.parametrize('response', [1, 2, 3, 4])
@mock.patch('realestate.app.user_inputs.input')
def test_export_options_valid_choice(mock_choice, response):
    mock_choice.return_value = response
    export_option = user_inputs.export_options()
    assert export_option == response

这样做的唯一方法是使用unittest模块进行子测试吗?我知道pytest不支持子测试,但我希望有类似类型的黑客。使用测试参数化。看见