[英]How to pass parameters to modify a decorator that takes a function with parameters
[英]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.