В upvoted комментарий к общепринятом ответ , Джо спрашивает:
Есть ли способ напечатать на консоль И записать вывод, чтобы он отображался в отчете о Junit?
В UNIX это обычно упоминается как тиинг . В идеале, пи-тест будет использоваться по умолчанию, а не в виде захвата. Не в идеале, ни py.test, ни какой-либо существующий сторонний плагин py.test (... в любом случае, о котором я знаю ) не поддерживают teee - несмотря на то, что Python тривиально поддерживает teeing " из коробки" .
Обезьяны-патчи py.test делать что-либо неподдерживаемое нетривиально. Почему? Потому что:
- Большинство функций py.test заблокированы частным
_pytest
пакетом, который не предназначен для внешнего импорта. Попытка сделать это, не зная, что вы делаете, обычно приводит к тому, что публичный pytest
пакет вызывает неясные исключения во время выполнения. Большое спасибо, py.test. Действительно надежная архитектура у вас там.
- Даже если вы делаете понять, как обезьяна-патч частного
_pytest
API безопасным образом, вы должны сделать это прежде , чем запустить публичный pytest
запуск пакета внешней py.test
команды. Вы не можете сделать это в плагине (например, conftest
модуль верхнего уровня в вашем наборе тестов). К тому времени py.test лениво получает вокруг , чтобы динамически импортировать плагин, любой py.test класс вы хотели обезьяньего патч уже давно был создан экземпляр - и вы не имеете доступа к этому экземпляру. Это подразумевает, что, если вы хотите, чтобы ваш monkey-patch применялся осмысленно, вы больше не можете безопасно запускать внешнюю py.test
команду. Вместо этого вы должны обернуть выполнение этой команды пользовательскими настройкамиtest
подайте команду (по порядку):
- Обезьяна-патчи частного
_pytest
API.
- Вызывает публичную
pytest.main()
функцию для запуска py.test
команды.
Этот ответ monkey-patches py.test's -s
и --capture=no
опции для захвата stderr, но не stdout. По умолчанию эти параметры не захватывают ни stderr, ни stdout. Конечно, это не совсем так. Но каждое великое путешествие начинается с утомительного приквела, который все забывают через пять лет.
Зачем это делать? Я сейчас скажу вам. Мой набор тестов на основе py.test содержит медленные функциональные тесты. Отображение стандартного вывода этих тестов полезно и обнадеживает, предотвращая достижение leycec,killall -9 py.test
когда еще один продолжительный функциональный тест не может что-либо делать в течение нескольких недель подряд. Однако отображение stderr этих тестов не позволяет py.test сообщать о трассировках исключений при неудачных тестах. Что совершенно бесполезно. Следовательно, мы принудительно используем py.test для захвата stderr, но не stdout.
Прежде чем мы перейдем к нему, этот ответ предполагает, что у вас уже есть настраиваемая test
команда setuptools, вызывающая py.test. Если вы этого не сделаете, см Руководства по интеграции подразделу хорошо написанного py.test в Надлежащей практике страницы.
Вы не устанавливать pytest-бегун , сторонние Setuptools плагин Заказное Setuptools test
команда также применение py.test. Если pytest-runner уже установлен, вам, вероятно, потребуется удалить этот пакет pip3, а затем применить ручной подход, указанный выше.
Предполагая, что вы следовали инструкциям в Ручной интеграции, выделенным выше, ваша база кода должна теперь содержать PyTest.run_tests()
метод. Измените этот метод, чтобы он напоминал:
class PyTest(TestCommand):
.
.
.
def run_tests(self):
# Import the public "pytest" package *BEFORE* the private "_pytest"
# package. While importation order is typically ignorable, imports can
# technically have side effects. Tragicomically, that is the case here.
# Importing the public "pytest" package establishes runtime
# configuration required by submodules of the private "_pytest" package.
# The former *MUST* always be imported before the latter. Failing to do
# so raises obtuse exceptions at runtime... which is bad.
import pytest
from _pytest.capture import CaptureManager, FDCapture, MultiCapture
# If the private method to be monkey-patched no longer exists, py.test
# is either broken or unsupported. In either case, raise an exception.
if not hasattr(CaptureManager, '_getcapture'):
from distutils.errors import DistutilsClassError
raise DistutilsClassError(
'Class "pytest.capture.CaptureManager" method _getcapture() '
'not found. The current version of py.test is either '
'broken (unlikely) or unsupported (likely).'
)
# Old method to be monkey-patched.
_getcapture_old = CaptureManager._getcapture
# New method applying this monkey-patch. Note the use of:
#
# * "out=False", *NOT* capturing stdout.
# * "err=True", capturing stderr.
def _getcapture_new(self, method):
if method == "no":
return MultiCapture(
out=False, err=True, in_=False, Capture=FDCapture)
else:
return _getcapture_old(self, method)
# Replace the old with the new method.
CaptureManager._getcapture = _getcapture_new
# Run py.test with all passed arguments.
errno = pytest.main(self.pytest_args)
sys.exit(errno)
Чтобы включить этот monkey-patch, запустите py.test следующим образом:
python setup.py test -a "-s"
Stderr, но не stdout, теперь будет захвачен. Острота!
Расширение вышеприведенного патча обезьяны на tedout и stderr оставлено в качестве упражнения для читателя с бочкой свободного времени.