【问题标题】:Writing unittest for python3 shell based on cmd module基于cmd模块为python3 shell编写unittest
【发布时间】:2015-12-28 20:25:10
【问题描述】:

我正在尝试为我的项目编写一些单元测试,但是在为 cmd 模块的功能编写单元测试时遇到了问题。

我按照这个问题的例子:Create automated tests for interactive shell based on Python's cmd module

让我们考虑以下内容:

#!/usr/bin/env python3

import cmd
import sys


class Interpreter(cmd.Cmd):
    def __init__(self, stdin=sys.stdin, stdout=sys.stdout):
        cmd.Cmd.__init__(self, stdin=stdin, stdout=stdout)

    def do_show(self, args):
        print("Hello world!")

if __name__ == "__main__":
    interpreter = Interpreter()
    interpreter.onecmd("show")

这是我的单元测试:

import unittest
import unittest.mock
import main
import sys


class CmdUiTest(unittest.TestCase):
    def setUp(self):
        self.mock_stdin = unittest.mock.create_autospec(sys.stdin)
        self.mock_stdout = unittest.mock.create_autospec(sys.stdout)

    def create(self):
        return main.Interpreter(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_show_command(self):
        cli = self.create()
        cli.onecmd("show")
        self.assertEqual("Hello world!", self._last_write(1))

如果我理解正确,在 sys.stdin 和 sys.stdout 的 unittest 模拟中正在创建,并且使用方法 _last_write() 我应该能够访问使用 self.mock_stdout.write.call_args_list[-nr:] 写入模拟标准输出的参数列表

测试结果

/home/john/rextenv/bin/python3 /home/john/pycharm/helpers/pycharm/utrunner.py /home/john/PycharmProjects/stackquestion/tests/test_show.py::CmdUiTest::test_show_command true
Testing started at 20:55 ...
Hello world!

Process finished with exit code 0

Failure
Expected :'Hello world!'
Actual   :''
 <Click to see difference>

Traceback (most recent call last):
  File "/home/john/PycharmProjects/stackquestion/tests/test_show.py", line 25, in test_show_command
    self.assertEqual("Hello world!", self._last_write(1))
AssertionError: 'Hello world!' != ''
- Hello world!
+ 

如您所见,Hello 世界!来自do_show() 实际上打印到标准输出。但由于某种原因,self.mock_stdout.write.call_args_list 总是返回空列表。

(顺便说一句。我正在从 Pycharm 运行测试,但我也尝试从 shell 执行它们,没有区别)

我所需要的只是能够以某种方式测试我的 cmd 解释器的功能。只需比较打印输出。

我也尝试模拟内置打印,但这更破坏了我的测试(实际代码和测试更复杂)。但我不相信模拟 print 和检查 called_with() 真的没有必要或正确的解决方案。模拟标准输出应该是可能的。

【问题讨论】:

    标签: python unit-testing python-3.x cmd python-unittest


    【解决方案1】:

    和orld有区别 不知道这是不是你想要的,last_write 肯定不行!

    F
    ======================================================================
    FAIL: test_show_command (__main__.CmdUiTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "./int.py", line 32, in test_show_command
        self.assertEqual('Hello World!', fakeOutput.getvalue().strip())
    AssertionError: 'Hello World!' != 'Hello world!'
    - Hello World!
    ?       ^
    + Hello world!
    ?       ^
    
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.003s
    
    FAILED (failures=1)
    

    改用 unitte.mock.patch - 我的 python 版本是 3.5

    from unittest.mock import patch
    from io import StringIO
    
    
        # not working for reasons unknown
        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:]))
    
        # modified with unittest.mock.patch
        def test_show_command(self):
            # Interpreter obj
            cli = self.create()
            with patch('sys.stdout', new=StringIO()) as fakeOutput:
                #print ('hello world')
                self.assertFalse(cli.onecmd('show'))
            self.assertEqual('Hello World!', fakeOutput.getvalue().strip())
    

    【讨论】:

    • 谢谢。虽然很奇怪为什么 _last_write() 不起作用。当提供除标准输出以外的其他内容时,似乎 cmd 模块完全跳过了 .write() 。可能是 cmd 模块中的错误。
    猜你喜欢
    • 2015-07-15
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 2021-04-27
    • 2017-08-16
    • 2020-09-03
    • 1970-01-01
    • 2021-01-12
    相关资源
    最近更新 更多