W upvoted komentarzu do akceptowanej odpowiedzi , Joe pyta:
Czy jest jakiś sposób drukowania na konsoli ORAZ przechwytywania danych wyjściowych, aby były widoczne w raporcie programu Junit?
W UNIX jest to powszechnie określane jako teeing . Idealnie, teeing zamiast przechwytywania byłby domyślnym py.test. Idealnie, ani py.test, ani żadna istniejąca wtyczka py.test innej firmy (... o której wiem, w każdym razie ) obsługuje teeing - pomimo że Python trywialnie wspiera teeing out-of-the-box .
Łapanie małp py.test, aby zrobić coś nieobsługiwanego, nie jest trywialny. Dlaczego? Ponieważ:
- Większość py.test funkcjonalność jest zamknięty za prywatny
_pytest
pakiet nie ma być importowany z zewnątrz. Próba zrobienia tego bez wiedzy o tym, co robisz, zwykle powoduje, że pytest
pakiet publiczny podnosi niejasne wyjątki w czasie wykonywania. Bardzo dziękuję, test py. Naprawdę solidna architektura, którą tam masz.
- Nawet jeśli zrobić dowiedzieć się, jak małpa-załatać prywatną
_pytest
API w sposób bezpieczny, trzeba to zrobić przed uruchomieniem publicznego pytest
uruchomiony pakiet przez zewnętrznego py.test
polecenia. Nie możesz tego zrobić we wtyczce (np. W conftest
module testowym najwyższego poziomu ). Zanim py.test leniwie zacznie dynamicznie importować wtyczkę, każda klasa py.test, którą chciałeś załatać, już dawno została utworzona - i nie masz dostępu do tej instancji. Oznacza to, że jeśli chcesz, aby łatka małpy została znacząco zastosowana, nie możesz już bezpiecznie uruchomić zewnętrznego py.test
polecenia. Zamiast tego musisz zawinąć uruchomienie tego polecenia za pomocą niestandardowych narzędzi konfiguracyjnychtest
polecenie, które (w kolejności):
- Łata łata prywatny
_pytest
interfejs API.
- Wywołuje funkcję publiczną w
pytest.main()
celu uruchomienia py.test
polecenia.
Ta odpowiedź zawiera łatki py.test -s
i --capture=no
opcje przechwytywania stderr, ale nie stdout. Domyślnie te opcje nie wychwytują stderr ani stdout. Oczywiście nie jest to zbyt ekscytujące. Ale każda wielka podróż zaczyna się od żmudnego prequela, o którym wszyscy zapomną za pięć lat.
Czemu to robić? Teraz ci powiem. Mój pakiet testowy oparty na py.test zawiera powolne testy funkcjonalne. Wyświetlanie standardowego przebiegu tych testów jest pomocne i uspokajające, zapobiegając sięgnięciu po leycec,killall -9 py.test
gdy kolejny długotrwały test funkcjonalny nic nie robi przez wiele tygodni. Wyświetlanie stderr tych testów uniemożliwia jednak py.test zgłaszanie śledzenia wyjątków w przypadku niepowodzeń testu. Co jest całkowicie nieprzydatne. Dlatego zmuszamy py. Test do przechwytywania stderr, ale nie stdout.
Zanim do tego przejdziemy, ta odpowiedź zakłada, że masz już niestandardowe test
polecenie setuptools wywołujące py.test. Jeśli nie, zapoznaj się z podsekcją Ręczna integracja dobrze napisanej strony dobrych praktyk py.test .
Czy nie instalować pytest-runner , a setuptools osób trzecich plugin zapewnienie zwyczaj setuptools test
komendy również powołując py.test. Jeśli pytest-runner jest już zainstalowany, prawdopodobnie będziesz musiał odinstalować ten pakiet pip3, a następnie zastosować ręczne podejście opisane powyżej.
Zakładając, że postępowałeś zgodnie z instrukcjami podanymi powyżej w Integracji ręcznej , twoja baza kodu powinna teraz zawierać PyTest.run_tests()
metodę. Zmodyfikuj tę metodę, aby przypominała:
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)
Aby włączyć tę łatkę dla małp, uruchom py.test w następujący sposób:
python setup.py test -a "-s"
Stderr, ale nie stdout, zostanie teraz przechwycony. Sprytne!
Rozciągnięcie powyższej łatki małpy na tee stdout i stderr pozostawia się jako ćwiczenie dla czytelnika z beczką pełną wolnego czasu.