Я играю с прибором monkeypatch в pytest, пытаясь смоделировать текущий размер окна терминала.
import os
import pytest
def get_terminal_size():
terminal_size = os.popen('stty size', 'r').read()
return terminal_size
def test_get_terminal_size(monkeypatch):
# The get_terminal_size() function will return a string 'height width\n'
def mock_size():
return '10 20\n'
monkeypatch.setattr(os.popen('stty size', 'r'), 'read', mock_size)
assert get_terminal_size() == '10 20\n'
Когда я запускаю pytest, я получаю ошибку подтверждения:
__________________________________________________________________ test_get_terminal_size __________________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f5bf1ec0cf8>
def test_get_terminal_size(monkeypatch):
# The get_terminal_size() function will return a string 'height width\n'
def mock_size():
return '10 20\n'
monkeypatch.setattr(os.popen('stty size', 'r'), 'read', mock_size)
> assert get_terminal_size() == '10 20\n'
E AssertionError: assert '' == '10 20\n'
E + 10 20
test_monkeypatch.py:15: AssertionError
Похоже, он не устанавливает mock_size. Я пытался следовать шаблону из документации Pytest
Есть ли какие-либо предложения о том, как заставить это работать?
Заранее спасибо!
Обновление: Как указал Кент Шикама в ответе ниже, для способа, которым я пытался захватить вывод, мне нужно было использовать флаг -s, чтобы отключить захват пестицидов.
Но с дальнейшими исследованиями об использовании popen, в частности, о переходе от использования os.popen к подпроцессу. Откройте, см. здесь и некоторую помощь из этого SO post на "Как подделать Попен" Я нашел решение.
вот новая настройка:
# \mokeypatch_popen.py
from subprocess import Popen
def get_terminal_size():
terminal_size = Popen('stty size', shell=True)
return terminal_size
Функция тестирования:
# \test_monkeypatch.py
import pytest
import monkeypatch_popen
def test_get_terminal_size(monkeypatch):
# The get_terminal_size() function will return a string 'height width\n'
def mock_terminal_size(cmd, **kwargs):
return '10 20\n'
monkeypatch.setattr(m_patch, 'Popen' , mock_terminal_size)
assert m_patch.get_terminal_size() == '10 20\n'
Поначалу для меня неочевидным было то, что функция mock_terminal_size будет обрабатывать параметры метода Popen, над которым она работает, поэтому она должна принимать параметры, используемые Popen в исходной функции. Я мог бы специально добавить параметр оболочки в mock_terminal_size, но, поскольку Popen принимает длинный список kwargs, я был немного более неоднозначным.
Это теперь проходит, когда я запускаю pytest, и флаг -s не нужен, так как я я больше не пытаюсь захватить вывод, но высмеиваю выполнение метода Popen.