【问题标题】:Pytest not looping while testing with monkeypatchingPytest在使用monkeypatching进行测试时没有循环
【发布时间】:2022-01-05 17:40:27
【问题描述】:

我对编程很陌生,我正在编写一些代码来收集用户的信息并将其添加到电子表格中。这是我要测试的基础:

# let's say this file is called collect.py

def infoBreakdown():
    userData = input("Enter a detail about your info: ")
    # add detail to a new column
    
    assignLetter = input("Want to assign a letter to this detail? (y/n) ")
    
    addLetter = False
    if assignLetter == "y":
        addLetter = True
    while addLetter:
        newLetter = input("Enter a letter to assign to this detail: ")
        # add letter to a single cell within that column
        # each additional letter adds to the same cell

        newLetter = input("Want to assign another letter for this detail?: ")
        if newLetter == "n":
            addLetter = False


def main():
    
    infoBreakdown()

    addInfo = True
    while addInfo:
        newInfo = input("Cool! Want to add more info? (y/n) ")
        if newInfo == "y":
            infoBreakdown()
        else:
            addInfo = False

main()

所以我希望我的测试能够循环添加多个细节和字母,但由于某种原因,它只运行一次 while 循环(我知道是因为我添加了几个标志来确保)。更令人困惑的是它只承认 第二次 运行而不是第一次运行。这是我的测试代码:

def input_main(prompt):
    inputRequest = {
        "Enter a detail about your info: ": "Detail #1",
        "Want to assign a letter to this detail? (y/n) ":, "y",
        "Enter a letter to assign to this detail: ":, "A",
        "Want to assign another letter for this detail? (y/n) ":, "y",
        "Enter a letter to assign to this detail: ":, "B",
        "Want to assign another letter for this detail? (y/n) ":, "n",
        "Cool! Want to add more info? (y/n) ": "y",
        "Enter a detail about your info: ": "Detail #2",
        "Want to assign a letter to this detail? (y/n) ":, "n",
        "Cool! Want to add more info? (y/n) ": "n"
}

    return inputRequest[prompt]

def test_main(monkeypatch):

    monkeypatch.setattr('builtins.input', input_main)

    assert collect.main() == None

所以我希望在电子表格中同时看到“Detail #1”(以及带有“AB”的单元格)和“Detail #2”,但是当我运行时它只有“Detail #2”考试。这告诉我这可能不是覆盖电子表格的问题,因为它们被输入到不同的列中。

如果我只针对第一个细节运行它,那么我希望在电子表格上看到“Detail #1”和一个带有“AB”的单元格,但它只有“Detail #1”和一个带有“B”的单元格”。

这仅在使用 pytest 时发生 - 如果我手动测试,代码运行良好。问题是我要求的输入比这多得多,手动测试非常浪费时间。对我所缺少的有任何见解吗?

【问题讨论】:

    标签: python testing while-loop pytest monkeypatching


    【解决方案1】:

    首先:对编程新手和从编写测试开始的赞誉。

    您的测试未按您预期的方式运行的原因是dict 无法按照您尝试使用它的方式运行。 dictunique 键到任意值的映射。虽然您的键不能,但您的值可以包含重复项。如果你调用print(len(InputRequest)),你会看到它只包含五个条目:

    {'Cool! Want to add more info? (y/n) ': 'n',
     'Enter a detail about your info: ': 'Detail #2',
     'Enter a letter to assign to this detail: ': 'B',
     'Want to assign a letter to this detail? (y/n) ': 'n',
     'Want to assign another letter for this detail? (y/n) ': 'n'}
    

    如果您编写带有重复键的 dict-literal,则重复键只会映射到您分配给它们的最后一个值。这就是为什么您只在输出中看到“Detail #2”的原因。您的测试只运行一次循环,因为您的最后一个条目应该完成测试。

    当我编写模拟用户输入的测试时,我会使用 Generator 封闭在闭包中:

    def make_mock_input(generator):
        def mock_input(*args, **kwargs): # ignore any arguments
            return next(generator) # the state of the generator is stored in the enclosing scope of make_mock_input
    
        return mock_input
    
    
    def test_main(monkeypatch):
        def input_generator(user_input):
            yield from user_input
    
        user_input = ("Detail #1", "y", "A", "y", "B", "n", "y", "Detail #2", "n", "n")
        gen = input_generator(user_input) # create the generator from your input values
        mock_input = make_mock_input(gen)
    
        monkeypatch.setattr("builtins.input", mock_input)
    
        assert collect.main() is None # do identity checks with 'is', add checks for output
    

    这样,您的模拟输入函数将在每次调用时返回序列中的下一个值(忽略所有传递的参数),就像用户输入他们的下一个值一样。

    我不得不说,虽然您的测试现在应该可以运行,但它并不是一个很好的测试。因为测试的想法是在某些事情没有按预期工作时提出AssertionError。现在你的测试几乎总是会通过,因为collect.main() 将总是返回None,如果其中没有引发异常。您应该添加更多断言语句,以编程方式检查输出的有效性。但我相信您会发现大量有关编写良好测试的资源。

    【讨论】:

    • 哇,非常感谢你,你是救生员!!我每天都在学习新东西!注意到测试 - 我现在主要专注于确保电子表格得到正确更新,但我肯定会为我的实际程序输出编写测试以供练习:)
    猜你喜欢
    • 2018-06-01
    • 1970-01-01
    • 2023-04-04
    • 2019-12-17
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多