Come posso vedere l'output di stampa normale creato durante l'esecuzione di Pytest?


401

A volte voglio solo inserire alcune dichiarazioni di stampa nel mio codice e vedere cosa viene stampato quando lo esercito. Il mio solito modo di "esercitare" è con i test di pytest esistenti. Ma quando eseguo questi, non riesco a vedere alcun output standard (almeno da PyCharm, il mio IDE).

Esiste un modo semplice per visualizzare l'output standard durante una corsa Pytest?


Solo in caso di fallimento o sempre?

17
-s disabilita l'acquisizione per test
hpk42

3
@delnan - Mi piacerebbe vederlo sempre
Des

Risposte:



51

In un commento votato alla risposta accettata , Joe chiede:

Esiste un modo per stampare sulla console E acquisire l'output in modo che venga visualizzato nel rapporto junit?

In UNIX, questo è comunemente indicato come tee . Idealmente, il tee anziché l'acquisizione sarebbe l'impostazione predefinita py.test. Non idealmente, né py.test né alcun plug-in py.test di terze parti esistente (... che conosco, comunque ) supporta il tee - nonostante Python supporti banalmente il tee out-of-the-box .

Il py.test di patch delle scimmie per fare qualsiasi cosa non supportata non è banale. Perché? Perché:

  • La maggior parte delle funzionalità di py.test è bloccata dietro un _pytestpacchetto privato che non deve essere importato esternamente. Tentare di farlo senza sapere cosa stai facendo di solito porta al pytestpacchetto pubblico a sollevare oscure eccezioni in fase di esecuzione. Grazie mille, py.test. Architettura davvero robusta che ci sei arrivato.
  • Anche quando si fa capire come la scimmia-patchare il privato _pytestAPI in modo sicuro, si deve fare in modo prima di eseguire il pubblico pytestrun pacchetto esterno py.testdi comando. Non è possibile farlo in un plug-in (ad esempio, un conftestmodulo di livello superiore nella suite di test). Quando py.test inizia pigramente a importare dinamicamente il tuo plug-in, qualsiasi classe py.test che desideri scimmiottare è stata istanziata da tempo - e non lo hai accesso a quell'istanza. Ciò implica che, se si desidera applicare in modo significativo la patch di scimmia, non è più possibile eseguire in sicurezza il comando esterno . Invece, devi concludere l'esecuzione di quel comando con uno strumento di installazione personalizzato ordini (in ordine): py.testtest
    1. Monkey corregge l' _pytestAPI privata .
    2. Chiama la pytest.main()funzione pubblica per eseguire il py.testcomando.

Questa risposta scimmia-patch py.test -se --capture=noopzioni per catturare stderr ma non stdout. Per impostazione predefinita, queste opzioni non catturano né stderr né stdout. Questo non è abbastanza stuzzicante, ovviamente. Ma ogni grande viaggio inizia con un noioso prequel che tutti dimenticano in cinque anni.

Perché farlo Ora te lo dirò. La mia suite di test basata su py.test contiene test funzionali lenti. Visualizzare lo stdout di questi test è utile e rassicurante, impedendo a Leycec di raggiungere killall -9 py.testquando ancora un altro test funzionale di lunga durata non riesce a fare nulla per settimane. La visualizzazione dello standard di questi test, tuttavia, impedisce a py.test di segnalare traceback delle eccezioni in caso di errori dei test. Che è del tutto inutile. Quindi, costringiamo py.test a catturare stderr ma non stdout.

Prima di arrivare ad essa, questa risposta presuppone che tu abbia già un testcomando setuptools personalizzato che richiama py.test. In caso contrario, consultare la sottosezione Integrazione manuale della pagina Buone Pratiche ben scritta di py.test .

Evitare Non installare pytest-runner , un setuptools di terze parti plug fornendo un setuptools personalizzati testcomandano anche invocando py.test. Se pytest-runner è già installato, probabilmente dovrai disinstallare quel pacchetto pip3 e quindi adottare l'approccio manuale collegato sopra.

Supponendo che tu abbia seguito le istruzioni in Integrazione manuale evidenziate sopra, la tua base di codice dovrebbe ora contenere un PyTest.run_tests()metodo. Modifica questo metodo per assomigliare:

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)

Per abilitare questa patch scimmia, eseguire py.test come segue:

python setup.py test -a "-s"

Ora verrà catturato Stderr ma non Stdout . Nifty!

L'estensione della suddetta patch di scimmia per stdout e stderr viene lasciata come esercizio al lettore con una canna piena di tempo libero.


33

Quando si esegue il test, utilizzare l' -sopzione. Tutte le istruzioni di stampa exampletest.pyverranno stampate sulla console quando viene eseguito il test.

py.test exampletest.py -s

31

Secondo la documentazione di Pytest , la versione 3 di Pytest può disabilitare temporaneamente l'acquisizione in un test:

def test_disabling_capturing(capsys):
    print('this output is captured')
    with capsys.disabled():
        print('output not captured, going directly to sys.stdout')
    print('this output is also captured')

20

pytest cattura lo stdout dai singoli test e li visualizza solo a determinate condizioni, insieme al riepilogo dei test che stampa per impostazione predefinita.

Ulteriori informazioni di riepilogo possono essere visualizzate utilizzando l'opzione '-r':

pytest -rP

mostra l'output acquisito dei test superati.

pytest -rx

mostra l'output acquisito dei test non riusciti (comportamento predefinito).

La formattazione dell'output è più bella con -r rispetto a -s.


2
Questa è la vera risposta che stavo cercando! Grazie. (Avere lo stdout DOPO i risultati del test è desiderato. Quando sono interfogliati, le linee stampate perdono valore.)
bossylobster

18

Prova pytest -s -v test_login.pyper maggiori informazioni sulla console.

-v è breve --verbose

-s significa "disabilita tutte le acquisizioni"




1
se stai usando il file pytest.ini puoi usare: addopts = -s -v python_files = test_login.py
timj98

4

Se si utilizza PyCharm IDE, è possibile eseguire quel singolo test o tutti i test utilizzando la barra degli strumenti Esegui. La finestra dello strumento Esegui visualizza l'output generato dalla tua applicazione e puoi vedere tutte le istruzioni di stampa presenti come parte dell'output del test.


Sai come stampare PyCharm mentre il test è in esecuzione? (invece che dopo il superamento del test)
Alexandre Huat

3

pytest --capture=tee-sysè stato recentemente aggiunto. Puoi catturare e vedere l'output su stdout / err.


-4

Le altre risposte non funzionano. L' unico modo per visualizzare l'output acquisito è utilizzare il seguente flag:

pytest: mostra tutto


6
--show-capture=allè il valore predefinito. L'aggiunta non ha alcun effetto.
hoefling
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.