Pytest testleri içinde oturum açma


94

Bazı durum değişkenlerini incelemek için test işlevi içine bazı günlük ifadeleri koymak istiyorum.

Aşağıdaki kod parçasına sahibim:

import pytest,os
import logging

logging.basicConfig(level=logging.DEBUG)
mylogger = logging.getLogger()

#############################################################################

def setup_module(module):
    ''' Setup for the entire module '''
    mylogger.info('Inside Setup')
    # Do the actual setup stuff here
    pass

def setup_function(func):
    ''' Setup for test functions '''
    if func == test_one:
        mylogger.info(' Hurray !!')

def test_one():
    ''' Test One '''
    mylogger.info('Inside Test 1')
    #assert 0 == 1
    pass

def test_two():
    ''' Test Two '''
    mylogger.info('Inside Test 2')
    pass

if __name__ == '__main__':
    mylogger.info(' About to start the tests ')
    pytest.main(args=[os.path.abspath(__file__)])
    mylogger.info(' Done executing the tests ')

Aşağıdaki çıktıyı alıyorum:

[bmaryada-mbp:/Users/bmaryada/dev/platform/main/proto/tests/tpch $]python minitest.py
INFO:root: About to start the tests 
======================================================== test session starts =========================================================
platform darwin -- Python 2.6.2 -- pytest-2.0.0
collected 2 items 

minitest.py ..

====================================================== 2 passed in 0.01 seconds ======================================================
INFO:root: Done executing the tests 

Yalnızca '__name__ == __main__'bloktan gelen günlük mesajlarının konsola iletildiğine dikkat edin.

pytestTest yöntemlerinden konsola günlüğe kaydetmeyi zorlamanın bir yolu var mı ?


3
Py.test'in yaratıcısı tarafından yayınlanan bu cevaba bir göz atabilirsiniz . Yüksek derecede çok yönlülük sağlayan en iyi eklenti önermektedir.
chb

Yanıtlar:


30

Benim için çalışıyor, işte aldığım çıktı: [Snip -> örnek yanlıştı]

Düzenleme: Görünüşe göre -sstdout'u yakalamaması için py.test seçeneğini geçmeniz gerekiyor. Burada (py.test kurulu değil) kullanmak yeterliydi python pytest.py -s pyt.py.

Kodunuzdaki için tek ihtiyacınız geçmektir -siçinde argsiçin main:

 pytest.main(args=['-s', os.path.abspath(__file__)])

Çıktı yakalamayla ilgili py.test belgelerine bakın .


Afedersiniz. Kodu aceleyle yapıştırdım. 'Sorunu' fark etmek için lütfen 'test_one' işlevinden 'assert 0 == 1'i kaldırın. Yalnızca bazı başarısızlıklar olduğunda (yanlış bir iddiada bulunarak bunu zorladım), py.test günlük bilgilerini yazdırıyor gibi görünüyor.
süper seçici

Sorun değil, programlı bir yol arayarak komut satırında nasıl düzelteceğimi öğrendim.
TryPyPy

1
ayrıca günlük çıktısını varsayılan örtük stderr yerine bir dosyaya yeniden yönlendirebilirsiniz.
hpk42

@superselector hpk42 py.test adamı, dinleyin. IIUC, sizin kodunuzda olacaktır logging.basicConfig(filename="somelog.txt", level=logging.DEBUG).
TryPyPy

128

3.3 sürümünden bu yana, pytestcanlı günlük kaydını destekler, yani testlerde yayınlanan tüm günlük kayıtları hemen terminale yazdırılacaktır. Özellik, Canlı Günlükler bölümünde belgelenmiştir . Canlı günlük kaydı varsayılan olarak devre dışıdır; etkinleştirmek log_cli = 1için pyproject.toml1 veya pytest.ini2 yapılandırmasında ayarlayın. Canlı kayıt, terminale ve dosyaya yaymayı destekler; ilgili seçenekler kayıtların özelleştirilmesine izin verir:

terminal:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

dosya:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

Not : log_clibayrak komut satırından geçirilemez ve ayarlanması gerekirpytest.ini . Diğer tüm seçenekler hem komut satırından geçirilebilir hem de yapılandırma dosyasında ayarlanabilir. As tarafından işaret Kévin Barré içinde bu yorumun yoluyla yapılabilir komut satırından ini seçenekleri geçersiz kılma, -o/--overrideopsiyon. Bunun yerine bildirmek log_clide pytest.ini, sadece çağırabilirsiniz:

$ pytest -o log_cli=true ...

Örnekler

Göstermek için kullanılan basit test dosyası:

# test_spam.py

import logging

LOGGER = logging.getLogger(__name__)


def test_eggs():
    LOGGER.info('eggs info')
    LOGGER.warning('eggs warning')
    LOGGER.error('eggs error')
    LOGGER.critical('eggs critical')
    assert True

Gördüğünüz gibi, ekstra bir konfigürasyona gerek yok; komut satırında pytestbelirtilen pytest.iniveya komut satırından iletilen seçeneklere göre kaydediciyi otomatik olarak kuracaktır .

Terminale, INFOseviyeye, süslü çıktıya canlı günlük kaydı

Yapılandırma pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"

Eski modeldeki aynı yapılandırma pytest.ini:

[pytest]
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S

Testi çalıştırmak:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
2018-08-01 14:33:20 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:33:20 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:33:20 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:33:20 [CRITICAL] eggs critical (test_spam.py:10)
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

Terminal ve dosyaya canlı kayıt, terminalde sadece mesaj ve CRITICALseviye, pytest.logdosyada fantezi çıktı

Yapılandırma pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "CRITICAL"
log_cli_format = "%(message)s"

log_file = "pytest.log"
log_file_level = "DEBUG"
log_file_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_file_date_format = "%Y-%m-%d %H:%M:%S"

Eski modeldeki aynı yapılandırma pytest.ini:

[pytest]
log_cli = 1
log_cli_level = CRITICAL
log_cli_format = %(message)s

log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S

Test sürüşü:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
eggs critical
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

$ cat pytest.log
2018-08-01 14:38:09 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:38:09 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:38:09 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:38:09 [CRITICAL] eggs critical (test_spam.py:10)

1 pyproject.toml sürüm 6.0'dan beri desteklenmektedir ve en iyi seçenek IMO'dur. Özellikler için PEP 518'e bakın .

2 Ayrıca yapılandırmak rağmen pytestiçinde setup.cfgaltında [tool:pytest]bölümüne yapmak cazip değil özel canlı kayıt formatı sağlamak istediğinizde söyledi. Okumakta olan diğer araçlar , dizi enterpolasyonu setup.cfggibi şeyleri ele %(message)salıp başarısız olabilir. En iyi seçenek pyproject.tomlyine de kullanmaktır , ancak eski ini tarzı formatı kullanmak zorunda kalırsanız, pytest.inihataları önlemek için bağlı kalın.


21
Notta Hakkında log_cliolmalıdır pytest.ini , bunu kullanabilir görünüyor -okomut satırından geçersiz kılma değeri seçeneği. pytest -o log_cli=true --log-cli-level=DEBUGbenim için çalışıyor.
Kévin Barré

@ KévinBarré çok güzel bir yorum ve genel olarak çok faydalı bir ipucu, teşekkürler! Cevap güncellendi.
hoefling

Bu kesinlikle günlük kaydı kullanırken doğru cevaptır. Testlerin içindeki logları ve test edilen sistem içerisinde bulunan ve ayrı ayrı ele alınması gereken logları ayırt etmeyi sevmeme rağmen .
CMCDragonkai

@CMCDragonkai maalesef pytestbu konuda biraz sınırlı. Ancak, bu, uygulamanızdaki testler için özel günlük kaydı yapılandırmasıyla yapılabilir; kaydedicilerinizdeki yaymayı kapatın ve belirli bir dosyaya günlük kaydeden bir "test işleyici" ekleyin. Bu şekilde, pytestyalnızca testlerden gelen kayıtları günlüğe kaydederken, özel işleyici SuT günlükleriyle ilgilenir.
hoefling

1
@OfekAgmon pytestçıktıyı saklamak istiyorsanız, --result-logargümanı kullanabilirsiniz (kullanımdan kaldırıldığını unutmayın , alternatifler burada ). pytestYine de çıktı ve canlı günlük çıktısını aynı dosyada depolayamazsınız .
hoefling
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.