使用 pytest,当所述方法提示输入另一个输入并且处于连续循环中时,如何测试输入是否会导致预期的方法调用?

Using pytest, how do you test that an input leads to an expected method call, when said method prompts for another input, and is in a continuous loop?

Substituting the built-in input function's value with a string 通常用于测试方法是否对该输入具有预期的响应。将使用像 monkeypatch 这样的工具来执行此操作,然后我们断言调用方法 returns 是预期值。

Even when you call another method inside the method,如果第二个有可预测的return值,你可以使用类似的方法。

现在,如果该方法的预期行为是调用一个也要求输入的方法怎么办?目的是确保程序到达第二个输入提示(确认第一个输入具有预期结果)。有没有办法单独断言?

示例:

class TwoInputs:

    def method_a(self):
        self.action = input("Enter something: ")
        if self.action == "jump":
            self.method_b()
            self.method_a()
        elif self.action == "exit":
            quit()

    def method_b(self):
        while True:
            self.action = input("Enter some other thing: ")
            if self.action == "1":
                print("Hello world.")
                break
            else:
                print("Invalid input.")

在上面的上下文中,您将如何测试 method_a 成功调用 method_b,并在那里结束测试?如果我通过将其更改为“跳跃”来对输入进行猴子修补,那么只需调用 method_a,相同的输入将在 method_b 中被视为无效,然后将连续循环。

要检查 method_b 是否已被调用,您必须模拟它。正如你提到的,你还必须模拟 input,并确保它的 returns 值会导致程序结束,而不是递归:

@mock.patch("two_inputs.TwoInputs.method_b")
@mock.patch("two_inputs.input")
@mock.patch("two_inputs.quit")
def test_that_a_calls_b(mock_quit, mock_input, mocked_method_b):
    # consecutive call results - second call is from inside `method_a`
    mock_input.side_effect = ["jump", "exit"]
    two_inputs = TwoInputs()
    two_inputs.method_a()
    mocked_method_b.assert_called_once()

这假设您的 class 位于项目根目录的 two_inputs.py

对于你的情况,我还添加了模拟系统函数 quit(否则测试会退出),但我猜你不会在你的真实代码中调用它。