Create automated tests for interactive shell based on Pythons cmd module

2024/9/20 0:06:32

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 optionsAvailable Options:------------------HOST      The IP address or hostname of the machine to interact withPORT      The TCP port number of the server on the HOST
md:> set HOST localhostHOST => 'localhost'
md:> set PORT 2222PORT => '2222'
md:>
Answer

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.

Moreover I use onecmd() to test even do_* (and occasionally help_*) methods and make my test less coupled to the code.

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_autospecclass 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.

https://en.xdnf.cn/q/72214.html

Related Q&A

Matplotlib with multiprocessing freeze computer

I have an issue with matplotlib and multiprocessing. I launch a first process, where I display an image and select an area, and close the figure. Then I launch another process, where I call a graph fun…

Pull Tag Value using BeautifulSoup

Can someone direct me as how to pull the value of a tag using BeautifulSoup? I read the documentation but had a hard time navigating through it. For example, if I had:<span title="Funstuff&qu…

What is the practical difference between xml, json, rss and atom when interfacing with Twitter?

Im new to web services and as an introduction Im playing around with the Twitter API using the Twisted framework in python. Ive read up on the different formats they offer, but its still not clear to m…

how to grab from JSON in selenium python

My page returns JSON http response which contains id: 14Is there a way in selenium python to grab this? I searched the web and could not find any solutions. Now I am wondering maybe its just not poss…

Numpy: Array of `arange`s

Is there a way to take...>>> x = np.array([0, 8, 10, 15, 50]).reshape((-1, 1)); ncols = 5...and turn it into...array([[ 0, 1, 2, 3, 4],[ 8, 9, 10, 11, 12],[10, 11, 12, 13, 14],[15, 16, 17…

Understanding model.summary Keras

Im trying to understand model.summary() in Keras. I have the following Convolutional Neural Network. The values of the first Convolution are: conv2d_4 (Conv2D) (None, 148, 148, 16) 448 …

Determine adjacent regions in numpy array

I am looking for the following. I have a numpy array which is labeled as regions. The numpy array represents a segmented image. A region is a number of adjacent cells with the same value. Each region h…

Python: win32gui.SetForegroundWindow

I have just written simple script to launch an applciation and I am trying to use "SendKeys" module to send keystrokes to this application. There is one "Snapshot" button, but I can…

Building PyCrypto with fastmath (gmp or mpir) via pip on Windows

I installed PyCrypto on Windows via pip but i was not able to build Crypto.PublicKey._fastmath because GMP was not found.I know there is a binary version on voidspace but i would like to build the late…

Get name of current test in setup using nose

I am currently writing some functional tests using nose. The library I am testing manipulates a directory structure. To get reproducible results, I store a template of a test directory structure and cr…