代码之家  ›  专栏  ›  技术社区  ›  GlenCrawford

接收和显示用户输入的doctesting函数-python(撕掉我的头发)

  •  6
  • GlenCrawford  · 技术社区  · 15 年前

    我目前正在用python(3.1)编写一个小应用程序,就像一个好孩子一样,我正在不断地修改测试。然而,我遇到了一种似乎无法进行理论检验的方法。它包含一个 input() 因为这个原因,我不完全确定应该把什么放在doctest的“expecting”部分。

    用于说明我的问题的示例代码如下:

    """
    >>> getFiveNums()
    Howdy. Please enter five numbers, hit <enter> after each one
    Please type in a number:
    Please type in a number:
    Please type in a number:
    Please type in a number:
    Please type in a number:
    """
    
    import doctest
    
    numbers = list()
    
    # stores 5 user-entered numbers (strings, for now) in a list
    def getFiveNums():
        print("Howdy. Please enter five numbers, hit <enter> after each one")
        for i in range(5):
            newNum = input("Please type in a number:")
            numbers.append(newNum)
        print("Here are your numbers: ", numbers)
    
    if __name__ == "__main__":
        doctest.testmod(verbose=True)
    

    当运行doctests时,程序在打印“expecting”部分后立即停止执行,等待我依次输入五个数字(无提示),然后继续。如下图所示:

    doctest results http://i39.tinypic.com/14904n5.jpg

    我不知道,如果有的话,我可以把它放在doctest的expecting部分,以便测试一个接收并显示用户输入的方法。所以我的问题是, 此功能是否已建立?

    3 回复  |  直到 14 年前
        1
  •  5
  •   Paul Hildebrandt    15 年前

    我知道你在要求一个doctest的答案,但是我可以建议这种类型的函数可能不是doctest的好候选者。我对文档使用doctest,而不是测试,因此doctest不会成为一个好的文档imho。

    最统一的方法可能看起来像:

    import unittest
    
    # stores 5 user-entered numbers (strings, for now) in a list
    def getFiveNums():
        numbers = []
        print "Howdy. Please enter five numbers, hit <enter> after each one"
        for i in range(5):
            newNum = input("Please type in a number:")
            numbers.append(newNum)
        return numbers
    
    def mock_input(dummy_prompt):
        return 1
    
    class TestGetFiveNums(unittest.TestCase):
        def setUp(self):
            self.saved_input = __builtins__.input
            __builtins__.input = mock_input
    
        def tearDown(self):
            __builtins__.input = self.saved_input
    
        def testGetFiveNums(self):
            printed_lines = getFiveNums()
            self.assertEquals(printed_lines, [1, 1, 1, 1, 1])
    
    if __name__ == "__main__":
        unittest.main()
    

    这也许不是对你提出的功能的精确测试,但你得到了这个想法。

        2
  •  5
  •   Mark Rushakoff    15 年前

    使这个可测试的最简单方法是 parameter injection :

    def getFiveNums(input_func=input):
        print("Howdy. Please enter five numbers, hit <enter> after each one")
        for i in range(5):
            newNum = input_func("Please type in a number:")
            numbers.append(newNum)
        print("Here are your numbers: ", numbers)
    

    实际上,您不能期望像那样对输入/输出进行单元测试——您不必担心调用 input 可能会以某种方式失败。您最好的选择是传入某种性质的存根方法;例如

    def fake_input(str):
        print(str)
        return 3
    

    所以在你的博士学位考试中 getFiveNums(fake_input) .

    此外,通过打破对 输入 现在 ,如果以后要将此代码移植到其他 没有 使用命令行,您可以直接插入新代码来检索输入(无论是GUI应用程序中的对话框,还是基于Web的应用程序中的javascript弹出窗口,等等)。

        3
  •  2
  •   Marlen T. B.    14 年前

    我找到了另一种方法。

    """
    >>> get_five_nums(testing=True)
    Howdy. Please enter five numbers, hit <enter> after each one.
    Please type in a number: 1
    Please type in a number: 1
    Please type in a number: 1
    Please type in a number: 1
    Please type in a number: 1
    Here is a list of the numbers you entered:  [1, 1, 1, 1, 1]
    >>>
    """
    
    import doctest
    
    numbers = []
    
    def get_five_nums(testing=False):
        """Stores 5 user-entered numbers (strings, for now) in a list."""
    
        print("Howdy. Please enter five numbers, hit <enter> after each one.")
        for i in range(5):
            new_num = int(input("Please type in a number: "))
            if testing:
                print(new_num)
            numbers.append(new_num)
        print("Here is a list of the numbers you entered: ", numbers)
    
    
    if __name__ == "__main__":
        doctest.testmod(verbose=True)  
    

    将上述代码保存在名为 P.Py . 现在制作一个名为 输入文件

    它所需要的就是。

    1
    1
    1
    1
    1
    

    五个。每行一个。

    要测试您的程序,请在终端或命令提示下执行以下操作(我使用的是Mac):

    $python foo.py<input.txt文件

    这对于任何程序上的任何类型的用户输入都是容易更改的。通过这个,您现在可以复制终端会话的输出并将其用作doctest。

    注:终端中的函数调用为 得到五个数字 . 在你的医生看来 获取五个数字(测试=真) .

    尽管doctest似乎并不打算以这种方式使用,但它仍然是一个方便的黑客。