繁体   English   中英

如何测试不带参数的函数

[英]How to test a Function that takes no parameters

我是这里的新手,也是编程新手(我只编程了 2 周)。 有没有人对如何测试不带参数的函数有任何建议。 我已经测试了带参数的函数,但没有测试过不带参数的函数。

在测试函数中,我尝试在 valid_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()

该函数将在没有参数的情况下工作,并且仍将作为用户输入,因为您在被调用的函数中有 input() 。

(注意:原始函数由于缩进而被破坏,所以在我修复它时,我冒昧地重写它以使其更简单。它仍然应该与您预期的原始实现和测试策略完全相同,这是真正的重点的问题,无论实现细节如何,都是完全相同的。)

一种方法是使用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语句用返回特定参数的Mock对象替换内置input函数。 在第一个测试中,它只返回'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很有用,另一个调用者可能会发现使用替代输出函数很有用。

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

那么你不应该做check_valid_column(a)因为a不是一个定义的变量,而是check_valid_column("a") ,所以用字符“a”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM