Come stampare su console in Pytest?


175

Sto cercando di utilizzare TDD (sviluppo test-driven) con pytest. pytestnon printalla console quando uso print.

Sto usando pytest my_tests.pyper eseguirlo.

La documentationsembra dire che dovrebbe funzionare per impostazione predefinita: http://pytest.org/latest/capture.html

Ma:

import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user = "alice"
        self.b = tum.Blogger(self.user)
        print "This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

Nulla viene stampato sulla mia console di output standard (solo i normali progressi e il numero di test superati / falliti).

E lo script che sto testando contiene print:

class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

Nel unittestmodulo, tutto viene stampato per impostazione predefinita, che è esattamente quello di cui ho bisogno. Tuttavia, desidero utilizzarlo pytestper altri motivi.

Qualcuno sa come mostrare le dichiarazioni di stampa?


1
Forse stdout viene sovrascritto. Cosa succede se lo usi sys.stdout.write("Test")? Che ne dici sys.__stdout__.write("Test")? Quest'ultimo dovrebbe sempre scrivere sullo stdout definito dal sistema, che dovrebbe essere la console. Se i due comandi fanno cose diverse, allora stdout viene modificato; se fanno la stessa cosa, allora il problema è qualcos'altro.
TheSoundDefense

Risposte:


205

Per impostazione predefinita, py.testacquisisce il risultato dello standard in modo che possa controllare come lo stampa. Se non lo facesse, emetterebbe molto testo senza il contesto di quale test ha stampato quel testo.

Tuttavia, se un test ha esito negativo, includerà una sezione nel rapporto risultante che mostra ciò che è stato stampato secondo lo standard in quel particolare test.

Per esempio,

def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

Risultati nel seguente output:

>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

Nota la Captured stdoutsezione.

Se desideri vedere le printistruzioni mentre vengono eseguite, puoi passare la -sbandiera a py.test. Tuttavia, si noti che a volte questo può essere difficile da analizzare.

>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================

2
Eminentemente pratico. Ottimo lavoro!
cmc,

1
hmm ... non registra ancora le mie dichiarazioni stampate
Tim Boland,

68

L'uso -sdell'opzione stamperà l'output di tutte le funzioni, che potrebbe essere troppo.

Se hai bisogno di un output particolare, la pagina del documento che hai citato offre alcuni suggerimenti:

  1. Inserisci assert False, "dumb assert to make PyTest print my stuff"alla fine della tua funzione e vedrai il tuo output a causa di un test fallito.

  2. PyTest ti ha passato un oggetto speciale e puoi scrivere l'output in un file per ispezionarlo in seguito, come

    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt", "w").write(err)
        open("out.txt", "w").write(out)

    Puoi aprire i file oute errin una scheda separata e consentire all'editor di aggiornarlo automaticamente per te, oppure eseguire un semplice py.test; cat out.txtcomando shell per eseguire il test.

Questo è un modo piuttosto abile di fare cose, ma potrebbe essere quello che ti serve: dopotutto, TDD significa che fai casino con le cose e lo lasci pulito e silenzioso quando è pronto :-).


ho provato la versione 1. con pytest 3.8.1 sfortunatamente stampa solo il blocco funzione di test, ma non l'output delle istruzioni di stampa :( altri trucchi per questo?
UV

@UV - Invece di usare la print()funzione, dovresti inserire la variabile o il messaggio che intendi stampare dopo la virgola nell'istruzione assert. Ad esempio assert False, what_are_you, "stampa" il valore di what_are_younel rapporto Pytest.
Mart Van de Ven,

43

Risposta breve

Usa l' -sopzione:

pytest -s

Risposta dettagliata

Dai documenti :

Durante l'esecuzione del test viene catturato qualsiasi output inviato a stdout e stderr . Se un test o un metodo di installazione falliscono, l'output acquisito di solito verrà mostrato insieme al traceback dell'errore.

pytestha l'opzione --capture=methodin cui methodè per test metodo cattura, e potrebbe essere uno dei seguenti: fd, syso no. pytestha anche l'opzione -sche è una scorciatoia per --capture=no, e questa è l'opzione che ti permetterà di vedere le tue istruzioni di stampa nella console.

pytest --capture=no     # show print statements in console
pytest -s               # equivalent to previous command

Impostazione dei metodi di acquisizione o disabilitazione dell'acquisizione

Esistono due modi in cui è pytestpossibile eseguire l'acquisizione:

  1. acquisizione del livello del descrittore di file (FD) (impostazione predefinita): verranno acquisite tutte le scritture che vanno ai descrittori di file del sistema operativo 1 e 2.

  2. acquisizione a livello di sys : verranno acquisite solo le scritture su file Python sys.stdout e sys.stderr. Non viene eseguita l'acquisizione di scritture su scrittori di file.

pytest -s            # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file

17

Avevo bisogno di stampare importanti avvertimenti sui test saltati esattamente quando PyTestdisattivato letteralmente tutto .

Non volevo fallire un test per inviare un segnale, quindi ho fatto un hack come segue:

def test_2_YellAboutBrokenAndMutedTests():
    import atexit
    def report():
        print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
    if sys.stdout != sys.__stdout__:
        atexit.register(report)

Il atexitmodulo mi consente di stampare elementi dopo aver PyTest rilasciato i flussi di output. L'output ha il seguente aspetto:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile: 
collected 15 items 

test_C_patch.py .....ssss....s.

===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$

Il messaggio viene stampato anche quando PyTestè in modalità silenziosa e non viene stampato se si esegue roba con py.test -s, quindi tutto è già ben testato.


1
Perfetto per fornire metriche di test personalizzate.
z0r


2

Inizialmente sono venuto qui per scoprire come PyTeststampare nella console di VSCode mentre eseguivo / debug il test unitario da lì. Questo può essere fatto con la seguente launch.jsonconfigurazione. Data .venvla cartella dell'ambiente virtuale.

    "version": "0.2.0",
    "configurations": [
        {
            "name": "PyTest",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "module": "pytest",
            "args": [
                "-sv"
            ],
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.venv",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }
    ]
}
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.