2015-12-28 3 views
2

Я пытаюсь написать некоторые unittests для моего проекта, но у меня возникают проблемы с написанием unittests для функциональности из модуля cmd.Написание unittest для оболочки python3 на основе модуля 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") 

И это мой UnitTest:

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

Если я понимаю правильно, в UnitTest издеваться из создаются sys.stdin и sys.stdout, а с помощью метода _last_write() я должен иметь доступ к списку аргументов, которые были написаны на насмешливый stdout нас ING 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! 
+ 

Как вы можете видеть Привет, мир! от do_show() фактически печатается на стандартный вывод. Но по какой-то причине self.mock_stdout.write.call_args_list всегда возвращает пустой список.

(Btw. Я бегу тесты от PyCharm, но я также пытался их выполнение из оболочки, без разницы)

Все, что мне нужно, чтобы быть в состоянии как-то тест функциональность моего CMD переводчика. Просто сравните выходные данные.

Я также попытался высмеять встроенный отпечаток, но это еще больше нарушило мой тест (более сложный код и тест). Но я не считаю, что насмешливая печать и проверка named_with() действительно не нужны или правильное решение. Издевательская stdout должна быть возможной.

ответ

2

Есть разница с Не уверен, что это то, что вы хотели, 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 - мой питон версия 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()) 
+1

Сойдет спасибо. Хотя странно, почему _last_write() не работает. Кажется, модуль cmd пропускает .write() вообще, когда поставляется что-то еще, чем stdout. Вероятно, ошибка в модуле cmd. – J91321

Смежные вопросы