如何测试不带参数的函数

2024-06-02 08:42:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我是新来的,不熟悉编程(我才编程两周)。有没有人对如何测试不带参数的函数有什么建议。我测试过带参数的函数,但没有不带参数的函数

在test函数上,我尝试传递一个参数,该参数应为有效的_letter()函数中的字母“a”。但它给出了一个错误,即没有定义“a”

def valid_letter():
    '''Function valid_letter
       Parameters None
       continuously asks for a valid letter
       if invalid data is provided
    '''
    while True:
        column = input("What column do you wish to select from a to g? ")
        if column != "a" and column != "b" and\
           column != "c" and column != "d" and\
           column != "e" and column != "f" and\
           column != "g" and column != "h":
           print("Your input is invalid")
           continue
        else:
         return column
         break  

def check_valid_column(expect):
    answer = valid_letter()
    print("Input: {}".format(answer))
    print("Expected: {}, Actual {}".format(expect, answer))

def main():

   check_valid_column(a)
main()

Tags: andto函数answerinput参数ifis
3条回答

该函数将不带参数工作,并且仍然与用户输入相同,因为您在调用的函数中有input()

您调用valid_letter()的方式很好。这不是问题所在。但您打算验证输入是否为“a”(显然代表正确答案)

因此,您不应该执行check_valid_column(a),因为a不是定义的变量,而是check_valid_column("a"),字符“a”也是如此

(注意:原来的函数由于缩进而被破坏,因此在我修复它时,我冒昧地重写了它以使其更简单。它的行为应与您预期的原始实现完全相同,并且测试策略(这是问题的真正焦点)与实现细节完全相同。)

一种方法是使用patch

def valid_letter() -> str:
    '''
    Prompts the user for a column between 'a' and 'g'.
    Continuously asks for a valid letter if invalid data is provided.
    '''
    while True:
        column = input("What column do you wish to select from a to g? ")
        if ord(column) in range(ord('a'), ord('g') + 1):
            return column
        print("Your input is invalid")


from unittest.mock import Mock, patch


def test_valid_letter() -> None:
    with patch('builtins.input', new=Mock(return_value='a')):
        assert valid_letter() == 'a'
    with patch('builtins.input', new=Mock(side_effect=['z', 'q', 'g', 'c'])):
        assert valid_letter() == 'g'


test_valid_letter()

测试中的patch语句将内置的input函数替换为返回特定参数的Mock对象。在第一个测试中,它只返回'a',因此我们断言valid_letter()将返回相同的值。在第二个测试中,每次调用它时,它都会从列表中返回连续的值;我们断言valid_letter()将继续在循环中调用它,直到它到达'g'

另一种方法是通过依赖项注入:

from typing import Callable
from unittest.mock import Mock


def valid_letter(input_func: Callable[[str], str]) -> str:
    '''
    Prompts the user for a column between 'a' and 'g', using input_func.
    Continuously asks for a valid letter if invalid data is provided.
    '''
    while True:
        column = input_func("What column do you wish to select from a to g? ")
        if ord(column) in range(ord('a'), ord('g') + 1):
            return column
        print("Your input is invalid")


def test_valid_letter() -> None:
    assert valid_letter(Mock(return_value='a')) == 'a'
    assert valid_letter(Mock(side_effect=['z', 'q', 'g', 'c'])) == 'g'


test_valid_letter()

在本例中,它不是让valid_letter调用内置的input函数,而是接受调用者提供的任意输入函数。如果你这样称呼它:

valid_letter(input)

然后,它的行为与原始的完全相同,但是调用方也可以传入任意替换,而不必使用patch。这使得测试更加容易,而且它还允许调用方包装或替换input以允许不同的UI样式。例如,如果在GUI应用程序中使用此函数,则调用方可以传递一个input_func,通过对话框而不是终端提示用户

相同的测试/注入逻辑适用于print函数。您可能会发现,让您的测试验证print在每次输入无效值时被调用是有用的,而另一个调用方可能会发现使用替代输出函数是有用的

相关问题 更多 >