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
_pytestpakiet nie ma być importowany z zewnątrz. Próba zrobienia tego bez wiedzy o tym, co robisz, zwykle powoduje, że pytestpakiet 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ą
_pytestAPI w sposób bezpieczny, trzeba to zrobić przed uruchomieniem publicznego pytesturuchomiony pakiet przez zewnętrznego py.testpolecenia. Nie możesz tego zrobić we wtyczce (np. W conftestmodule 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.testpolecenia. Zamiast tego musisz zawinąć uruchomienie tego polecenia za pomocą niestandardowych narzędzi konfiguracyjnychtest polecenie, które (w kolejności):
- Łata łata prywatny
_pytestinterfejs API.
- Wywołuje funkcję publiczną w
pytest.main()celu uruchomienia py.testpolecenia.
Ta odpowiedź zawiera łatki py.test -si --capture=noopcje 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 testpolecenie 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 testkomendy 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.