Pytest: mock / patch sys.stdin в программе, использующей потоки с python - PullRequest
0 голосов
/ 18 мая 2018

Я получил некоторый код, который мне нужно проверить перед рефакторингом.Он использует глубокую рекурсию, поэтому устанавливает новые ограничения и затем запускается в новом потоке:

sys.setrecursionlimit(10**6)
threading.stack_size(2**27)
...
threading.Thread(target=main).start()

Код в значительной степени опирается на sys.stdin и sys.stdout, например

class SpamClass:
    def read(self):
        self.n = int(sys.stdin.readline())
        ...
        for i in range(self.n):
            [a, b, c] = map(int, sys.stdin.readline().split())
    ...
    def write(self)
        print(" ".join(str(x) for x in spam()))

Для проверкикод, мне нужно передать содержимое ряда входных файлов и сравнить результаты с содержимым некоторых соответствующих выходных файлов образца.

До сих пор я безуспешно пробовал три или четыре различных типа насмешек и исправлений.Все остальные мои тесты написаны для pytest, поэтому было бы неудобно использовать что-то еще.

Я попытался установить патч module.sys.stdin с StringIO, который, похоже, не работает, потому что capsys pytest устанавливает sys.stdin в ноль и, следовательно, выдает ошибку, несмотря на патч.

Я также пытался использовать приспособление pytest monkeypatch для замены метода module.SpamClss.read на функцию, определенную в тесте, но это вызывает ошибку сегментации из-за, я думаю, потока, завершающего работу до теста(или же …?).

'pytest test_spam.py' terminated by signal SIGBUS (Misaligned address error)

Есть предложения, как это сделать правильно?Большое спасибо.

1 Ответ

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

Ну, я до сих пор не знаю, в чем была проблема, или я делаю это правильно, но пока это работает.Я не уверен, что многопоточность работает правильно, но в остальном все в порядке.

@pytest.mark.parametrize("inputs, outputs", helpers.get_sample_tests('spampath'))
def test_tree_orders(capsys, inputs, outputs):
    """
    """
    with patch('module.sys.stdin', StringIO("".join(inputs))):
        module.threading.Thread(target=module.main()).start()

    captured = capsys.readouterr()

    assert "".join(outputs) == captured.out

Для всех, кто заинтересован, это помогает сделать ваши отладочные отпечатки как print(spam, file=sys.stderr), к которым вы затем можете получить доступ в тесте как captured.err, ср.captured.out используется для тестирования.

...