6

我正在使用 Python 3 和 cmd 模块构建交互式外壳。我已经使用 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:>
4

2 回答 2

5

您可以mock input或将输入流传递给 cmd 以注入用户输入,但我发现通过onecmd() CmdAPI 方法对其进行更简单灵活的测试并相信如何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()返回,否则。TrueFalse

于 2015-05-06T07:46:38.127 回答
1

使用 python模拟库来模拟用户输入。在这里,您会发现示例1、2类似问题。

于 2015-05-05T19:14:07.460 回答