![](/img/trans.png)
[英]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.