基于Python的cmd模块为交互式shell创建自动化测试 [英] Create automated tests for interactive shell based on Python's cmd module
问题描述
我正在使用Python 3和cmd模块构建一个交互式shell.我已经使用py.test编写了简单的单元测试,以测试各个功能,例如do_ *功能.我想创建更全面的测试,通过模拟用户的输入与外壳本身进行实际交互.例如,如何测试以下模拟会话:
I am building an interactive shell using Python 3 and the cmd module. I have already written simple unit tests using py.test to test the individual functions, such as the do_* functions. I'd like to create more comprehensive tests that actually interact with the shell itself by simulating a user's input. 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:>
推荐答案
您可以mock
input
或传递到cmd的输入流来注入用户输入,但是我发现通过onecmd()
Cmd
如何读取输入.这样,您就不必关心Cmd
如何执行肮脏的工作并直接通过用户命令进行测试:我同时通过控制台和套接字使用cmd
,并且我不在乎流来自何处.
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. 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.
此外,我使用onecmd()
甚至可以测试do_*
(有时是help_*
)方法,并使测试与代码的耦合度降低.
Moreover I use onecmd()
to test even do_*
(and occasionally help_*
) methods and make my test less coupled to the code.
按照一个简单的示例说明如何使用它. create()
和_last_write()
是用于构建MyCLI
实例并分别获取最后一行输出的辅助方法.
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.
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
.
Take care that onecmd()
return True
if your cli should terminate, False
otherwise.
这篇关于基于Python的cmd模块为交互式shell创建自动化测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!