【问题标题】:How to use Black Box Test with stdin/stdout with python如何将黑盒测试与标准输入/标准输出与 python 结合使用
【发布时间】:2020-08-20 17:36:18
【问题描述】:

我喜欢 TDD,所以我一开始尝试写我的Black Box Test

这是一个处理stdin并像这样输出到stdout的python程序(我尝试编写自己的语言来处理stdin和stdout):

$ python3 ./minor.py
>>> print, "hello\nthis is a good morning"
... hello
  . this is a good morning
>>> $quit

但我不能模拟标准输入和标准输出。我尝试在 Python 中使用subprocess,但Popen.stdout.read() 挂起的EOF 需要终止程序。或者communicate(),但它会杀死我的程序并且它不能处理两个或更多的输入。

这让我沮丧了 2 天多,我找不到任何关于使用 stdin/stdout 进行模拟或黑盒测试的有用信息(我可以使用浏览器进行测试,但不能轻松使用 stdin/stdout 进行测试,这看起来很奇怪)。

谢谢。

*** First Editing ***

我创建了一个新的单元测试类来处理我的类。它具有创建新 Popen 对象的功能。

我尝试写信给stdin 并声明stdout...但它因为找不到EOF 而挂起。

我应该如何处理它才能做到?感谢您的帮助!

class TestFunc(unittest.TestCase):
    def run_minor(self):
        return Popen(['python3', './minor.py'],
                stdin = PIPE,
                stdout = PIPE,
                stderr = PIPE,
                text = True,
            )

    def test_print(self):
        prop = self.run_minor()

        self.assertEqual(prop.stdout.read(), '>>> ')

        prop.stdin.write("print, 'this'")
        self.assertEqual(prop.stdout.read(), '... this\n>>> ')

        prop.stdin.write("$quit")
        self.assertEqual(prop.stdout.read(), '')

        prop.kill()

【问题讨论】:

  • 当你说你不能模拟标准输入和标准输出时,我不确定我是否理解你的意思——sys.stdinsys.stdout 只是类似文件的对象,你可以将它们替换为其他类似文件的对象,它们的行为与您的测试要求不同。在某些情况下,您实际上需要覆盖 FD 0 和 FD 1,但 os.dup2() 可以轻松解决这些情况。
  • ...那么,你能告诉我们你做了什么来尝试来模拟标准输入或标准输出,以及你在尝试中遇到的显式失败模式吗?
  • @CharlesDuffy 好的,我正在编辑...
  • 这能回答你的问题吗? Python 3 unittest simulate user input
  • @Evgeny ,不,是的......我在想因为你的评论,我不能用另一个函数来模拟它!只是因为我需要测试它而不是模拟它。我想模拟的是input/output。顺便说一句,我在想如果使用函数来处理像字符串一样的输入/输出对我来说是可以的......输入,然后将其转换为字符串并返回一个字符串,然后输出......或者建立一个有状态的类。

标签: python testing black-box


【解决方案1】:

我创建了一个辅助类来帮助...我不知道这是否是最好的主意,但它非常有效:

class MinorMock(object):
    """
    The Mock of Minor Programme.

    Use method `input` and `assertOutput` to set the input and the output want. Use
    `assertInputMeetOutput` to check if the input is meet its output by unittest's object.
    """
    def __init__(self, test_obj):
        self.popen = Popen(['python3', 'minor.py'], stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True)
        self.input_text = ''
        self.output_text = ''
        self.err_text = ''
        self.test_obj = test_obj

    def input(self, text):
        self.input_text += text
        return self

    def assertOutput(self, text):
        self.output_text += text
        return self

    def assertError(self, text):
        self.err_text += text
        return self
    
    def assertInputMeetOutput(self):
        (out, err) = self.popen.communicate(self.input_text)
        self.test_obj.assertEqual(out, self.output_text)
        self.test_obj.assertEqual(err, self.err_text)
        self.popen.kill()

欢迎其他答案...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2013-09-18
    相关资源
    最近更新 更多