简体   繁体   English

基于Python的cmd模块为交互式shell创建自动化测试

[英]Create automated tests for interactive shell based on Python's cmd module

I am building an interactive shell using Python 3 and the cmd module. 我正在使用Python 3和cmd模块构建交互式shell。 I have already written simple unit tests using py.test to test the individual functions, such as the do_* functions. 我已经使用py.test编写了简单的单元测试来测试各个函数,例如do_ *函数。 I'd like to create more comprehensive tests that actually interact with the shell itself by simulating a user's input. 我想创建更全面的测试,通过模拟用户的输入实际上与shell本身进行交互。 For example, how could I test the following simulated session: 例如,我如何测试以下模拟会话:

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:>

You can mock input or input stream passed to cmd to inject user input but I find more simple and flexible test it by onecmd() Cmd API method and trust how Cmd read input. 您可以mock传递给cmd的input或输入流以注入用户输入,但我发现通过onecmd() Cmd API方法更简单灵活地测试它并信任Cmd如何读取输入。 In this way you cannot care how Cmd do the dirty work and test directly by users command: I use cmd both by console and socket and this I cannot care where the stream come from. 通过这种方式,您无法关心Cmd如何通过用户命令直接执行脏工作和测试:我通过控制台和套接字使用cmd ,这我不关心流来自何处。

Moreover I use onecmd() to test even do_* (and occasionally help_* ) methods and make my test less coupled to the code. 此外,我使用onecmd()来测试甚至do_* (偶尔help_* )方法,并使我的测试更少地耦合到代码。

Follow a simple example of how I use it. 按照我如何使用它的简单示例。 create() and _last_write() are helper methods to build a MyCLI instance and take the last output lines respectively. 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())

Take care that onecmd() return True if your cli should terminate, False otherwise. 如果你的cli应该终止,请注意onecmd()返回True ,否则返回False

Use python mock library to simulate user input. 使用python 模拟库来模拟用户输入。 Here you will find similar problems with examples 1 , 2 . 在这里你会找到的例子类似的问题12

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM