Тестирование python stdout при вводе - PullRequest
0 голосов
/ 17 мая 2018

Тест для следующего метода проверяет правильность стандартного вывода в подсказке.

Когда вызывается input (), он ждет, когда пользователь нажмет enter и прервет.Тест проходит автоматическим нажатием 'enter'.

Это хакерство, и должен быть лучший способ проверить этот метод.

МЕТОД :

class GameDisplay:

@staticmethod
def prompt(text):
    input_value = input(text)
    return input_value

ТЕСТ :

from pynput.keyboard import Key, Controller

class TestGameDisplay(unittest.TestCase):

@patch('sys.stdout', new_callable=StringIO)
def test_prompt_output(self, mock_stdout):
    keyboard = Controller()
    keyboard.press(Key.enter)
    self.gameDisplay.prompt('Choose 0: ')
    keyboard.release(Key.enter)
    self.assertEqual( mock_stdout.getvalue(), 'Choose 0: ')

if __name__ == '__main__':
   unittest.main()

ВЫХОД :

Разрыв строки в результате нажатия клавиши enter.

...................................
............................................
----------------------------------------------------------------------
Ran 79 tests in 0.113s

OK

TEST FIX ATTEMPT:

@patch('sys.stdout', new_callable=StringIO)
@patch('builtins.input', return_value='0')
def test_prompt_output(self, mock_stdout, input):
    self.gameDisplay.prompt('Choose 0: ')
    self.assertEqual( mock_stdout.getvalue(), 'Choose 0: ')

ВЫХОД:

FAIL: test_prompt_output (tests.test_game_display.TestGameDisplay)
self.assertEqual( mock_stdout.getvalue(), 'Choose 0: ')
AssertionError: <MagicMock name='input.getvalue()' id='4675607744'> != 'Choose 0: '

----------------------------------------------------------------------
Ran 79 tests in 0.015s

FAILED (failures=1)

1 Ответ

0 голосов
/ 17 мая 2018

mock_stdout только перехватывает стандартный вывод оператора print, поэтому добавьте print(text)

class GameDisplay:

    @staticmethod
    def prompt(text):
        input_value = input(text)
        print(text)
        return input_value

Этот кусок кода протестирован и работает как ожидалось

@mock.patch('sys.stdout', new_callable=StringIO)
@mock.patch('__builtin__.input', return_value='0')
def test_prompt_output3(self, mock_input, mock_stdout):
        p = GameDisplay.prompt('Choose 0: ')
        self.assertEqual(p, '0')
        self.assertEqual(mock_stdout.getvalue(), 'Choose 0: \n')

но тогда будет напечатано. Выберите 0: дважды

Проверить значение return_value prompt() должно быть достаточно в реальной жизни.

Остается только 1 опция, если вы действительно хотите смоделировать ввод и вывод одновременно.

Это подойдет, если вы не издеваетесь над print одновременно:

print(text)
input_value = input()

Или пойти по безумному пути, подделать стандартный вывод:

mock_stdout = StringIO('Choose 0: ')
p = GameDisplay.prompt('Choose 0: ')
self.assertEqual(mock_stdout.getvalue(), 'Choose 0: ')

или это похоже на присвоение return_value для фиктивного объекта:

with mock.patch('sys.stdout', new=StringIO("xxx")) as mock_stdout:
...