如何在while循环中包含的条件语句的基础上对功能进行单元测试

时间:2019-05-29 16:38:17

标签: python-3.x unit-testing while-loop mocking pytest

我想知道什么是最好的单元测试while循环的最佳方法,该循环仅在输入特定的输入时才会中断(有关更多详细信息,请参见代码)。我的测试实际上按预期工作,并且正确失败。但是,我觉得它是“被黑客入侵”的,并且不是测试这种代码的最佳方法。

当前,我必须通过模拟打破循环的用户输入来手动打破测试中的循环(有关更多详细信息,请参见代码)。我已经在pytest中尝试过参数化,但是,一旦我模拟了不会破坏循环的输入,测试就会陷入无限循环。它永远不会达到下一个参数化值。

正在测试的功能

def export_options():
    while True:
        try:
            choice = int(input("\nPlease make a selection"))
            if choice in range(1, 5):
                return choice
            else:
                 # I want to test this line when the input is bad
                print("\nNot a valid selection\n")  
        except ValueError as err:
            print("Please enter an integer")

测试功能

@mock.patch('realestate.app.user_inputs.print')
# The 1 is used to break the loop otherwise the test never ends!
@mock.patch('realestate.app.user_inputs.input', side_effect=[0, 5, 1])
def test_export_options_invalid_integer(mock_choice, mock_print):
    user_inputs.export_options()

    # Best way I could think of to test bad inputs. Anything that is less than 1 or greater than 4 will fail the test.
    # Make sure I call the correct print function
    mock_print.assert_called_with("\nNot a valid selection\n")
    # Make sure I call the correct print function twice
    assert mock_print.call_count == 2

我根据当前代码获得了想要的结果。但是,我想在可能的情况下使用最佳做法,并在处理仅根据特定用户输入中断 的while循环时,将其应用于以后的所有测试。

1 个答案:

答案 0 :(得分:1)

关于永不退出的“真实”无限循环:嵌入式系统上的进程有时是这样实现的,并且仅在系统因关机或被操作系统杀死而终止时才会终止。对于此类循环,典型的解决方案是将循环主体提取到单独的函数/方法中。

def main_loop():
    while True:
        main_body()

这样,您通过将代码提取到main_body中来最大化了可以进行单元测试的代码量。显然,main_loop仍然不能进行单元测试,但是可以在更高级别的测试中进行测试。

很显然,您的循环不是那种类型,因为您可以退出循环而不会杀死线程等。因此,我认为您原则上测试该功能的方法是正确的。

但是,有一些方法可以改善测试套件。举个例子:作为例子显示的测试用例已经是一个复杂的测试,我建议从更基础的测试开始:

  • 测试数字1是否被接受
  • 测试数字4是否被接受
  • 测试数字0是否被接受(序列:0,从1..4开始一个数字)
  • 测试是否接受数字5(顺序:5,是1..4中的一个)

如果这些测试中的任何一个失败,它将为您提供更直接的指示,表明问题可能出在哪里。这些测试尚未测试的内容(与您的测试相反)是,该例程是否将能够处理多个错误的输入,以及提示和错误消息是否符合预期。但是,这些是各个方面,因此将您的测试分为多个单独的测试是有意义的。