Как протестировать интерактивное python приложение с помощью pytest - PullRequest
1 голос
/ 15 марта 2020

У меня есть определение этой функции:

def interactive_mode():
    parking_query = Query()

    while(True):
        query = input()
        if query == 'exit':
            return -1
        else:
            parking_query.process(query)

Мне нужно протестировать эту функцию, используя pytest, как можно смоделировать input () в моем файле тестов, когда он находится внутри бесконечного l oop?

Кроме того, после имитации ввода мне нужно захватить вывод на каждый вход из stdout, что можно сделать с помощью capsys в pytest.

То, что я пытался сделать:

1.

monkeypatch.setattr('sys.stdin', io.StringIO(query))

Это дает и ошибка EOF, не работает!

2.

from unittest.mock import Mock

mock_stdin = Mock()
mock_stdin.readline = Mock(io.StringIO(query))

monkeypatch.setattr('sys.stdin', io.StringIO(query))

Get зависает бесконечно, когда я бегу pytest

Моя тестовая функция:

def test_interactive_mode(capsys, monkeypatch):
    '''
        Tests the interactive_mode() method by mocking
        stdin using monkeypatch and reading stdout using capsys
    '''
    testcases = [
        {
            'input':  [
                        'input query'
                      ],
            'output': [
                        'expected output response to query'
                      ] 
        }
    ]

    for case in testcases:
        for i, query in enumerate(case['input']):
            with mock.patch.object(builtins, 'input', lambda : query):
                # mock_stdin = Mock()
                # mock_stdin.readline = Mock(io.StringIO(query))

                # monkeypatch.setattr('sys.stdin', io.StringIO(query))

                return_value = interactive_mode()

                if return_value == -1:
                    break

                captured = capsys.readouterr()

                assert captured.out == case['output'][i] + '\n'

1 Ответ

2 голосов
/ 15 марта 2020

Найден хакерский способ решения проблемы, служит цели, но не предлагает идеальное решение!

def test_interactive_mode(capsys, monkeypatch):
    '''
        Tests the interactive_mode() method by mocking
        stdin using monkeypatch and reading stdout using capsys
    '''
    testcases = [
        {
            'input':  [
                        'input query'
                      ],
            'output': [
                        'expected output response to query'
                      ] 
        }
    ]

    for case in testcases:
        for i, query in enumerate(case['input']):
            with mock.patch('builtins.input', side_effect=[query, 'exit']):
                return_value = interactive_mode()

                if return_value == -1:
                    break

                captured = capsys.readouterr()

                assert captured.out == case['output'][i] + '\n'
...