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

Gle*_*ord 6 python doctest user-input

我目前正在用Python(3.1)编写一个小应用程序,就像一个好小男孩一样,我正在进行doctesting.但是,我遇到过一种我似乎无法进行doctest测试的方法.它包含一个input(),因此,我不完全确定在doctest的"期待"部分放置什么.

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

"""
>>> 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)
Run Code Online (Sandbox Code Playgroud)

在运行doctests时,程序在打印"Expecting"部分后立即停止执行,等待我一个接一个地输入五个数字(没有提示),然后继续.如下所示:

doctest结果http://i39.tinypic.com/14904n5.jpg

我不知道什么,如果有的话,我可以放在我的doctest的Expecting部分,以便能够测试接收然后显示用户输入的方法.所以我的问题(最后)是,这个函数是doctestable吗?

Mar*_*off 5

使这个可测试的最简单方法是参数注入:

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)
Run Code Online (Sandbox Code Playgroud)

你不能真实地期望单元测试输入/输出 - 你不能担心调用input可能会以某种方式失败.你最好的选择是传递某种性质的存根方法; 就像是

def fake_input(str):
    print(str)
    return 3
Run Code Online (Sandbox Code Playgroud)

所以在你的doctest中,你实际上是在测试getFiveNums(fake_input).

此外,通过打破input 现在的直接依赖性,如果您以后将此代码移植到其他使用命令行的其他内容,您可以直接删除新代码以检索输入(无论是否为对话框) GUI应用程序,或基于Web的应用程序中的Javascript弹出窗口等).


Pau*_*ndt 5

我知道你要求一个doctest答案,但我可以建议这种类型的功能可能不适合doctest.我使用doctests进行文档测试而不是测试,而doctest对此不会提供良好的文档恕我直言.

一种最独特的方法可能如下:

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()
Run Code Online (Sandbox Code Playgroud)

它可能没有准确地测试你提出的功能,但你明白了.