【问题标题】:Create automated tests for interactive shell based on Python's cmd module基于 Python 的 cmd 模块为交互式 shell 创建自动化测试
【发布时间】:2015-07-15 10:10:36
【问题描述】:

我正在使用 Python 3 和 cmd 模块构建一个交互式 shell。我已经使用 py.test 编写了简单的单元测试来测试各个函数,例如 do_* 函数。我想通过模拟用户的输入来创建更全面的测试,这些测试实际上与 shell 本身交互。例如,我如何测试以下模拟会话:

bash$ console-app.py
md:> show options
  Available Options:
  ------------------
  HOST      The IP address or hostname of the machine to interact with
  PORT      The TCP port number of the server on the HOST
md:> set HOST localhost
  HOST => 'localhost'
md:> set PORT 2222
  PORT => '2222'
md:>

【问题讨论】:

    标签: python python-3.x tdd pytest python-cmd


    【解决方案1】:

    您可以mock input 或将输入流传递给 cmd 以注入用户输入,但我发现通过onecmd() Cmd API 方法对其进行更简单灵活的测试,并相信Cmd 如何读取输入。这样你就不会关心Cmd 是如何做脏活并直接通过用户命令进行测试的:我通过控制台和套接字使用cmd,这我不在乎流来自哪里。

    此外,我甚至使用onecmd() 来测试do_*(有时是help_*)方法,并使我的测试与代码的耦合度降低。

    按照我如何使用它的简单示例。 create()_last_write() 是帮助方法来构建 MyCLI 实例并分别获取最后的输出行。

    from mymodule import MyCLI
    from unittest.mock import create_autospec
    
    class TestMyCLI(unittest.TestCase):
        def setUp(self):
            self.mock_stdin = create_autospec(sys.stdin)
            self.mock_stdout = create_autospec(sys.stdout)
    
        def create(self, server=None):
            return MyCLI(stdin=self.mock_stdin, stdout=self.mock_stdout)
    
        def _last_write(self, nr=None):
            """:return: last `n` output lines"""
            if nr is None:
                return self.mock_stdout.write.call_args[0][0]
            return "".join(map(lambda c: c[0][0], self.mock_stdout.write.call_args_list[-nr:]))
    
        def test_active(self):
            """Tesing `active` command"""
            cli = self.create()
            self.assertFalse(cli.onecmd("active"))
            self.assertTrue(self.mock_stdout.flush.called)
            self.assertEqual("Autogain active=False\n", self._last_write())
            self.mock_stdout.reset_mock()
            self.assertFalse(cli.onecmd("active TRue"))
            self.assertTrue(self.mock_stdout.flush.called)
            self.assertEqual("Autogain active=True\n", self._last_write())
            self.assertFalse(cli.onecmd("active 0"))
            self.assertTrue(self.mock_stdout.flush.called)
            self.assertEqual("Autogain active=False\n", self._last_write())
    
        def test_exit(self):
            """exit command"""
            cli = self.create()
            self.assertTrue(cli.onecmd("exit"))
            self.assertEqual("Goodbay\n", self._last_write())
    

    如果您的 cli 应该终止,请注意 onecmd() 返回 True,否则返回 False

    【讨论】:

      【解决方案2】:

      使用 python mock 库来模拟用户输入。在这里你会发现类似问题的例子1,2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-15
        • 1970-01-01
        • 2018-02-08
        • 1970-01-01
        相关资源
        最近更新 更多