簡體   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