Запис в рамках тестів pytest


90

Я хотів би помістити деякі оператори реєстрації в тестову функцію, щоб перевірити деякі змінні стану.

У мене є такий фрагмент коду:

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 ')

Я отримую такий результат:

[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 

Зверніть увагу, що лише повідомлення журналу з '__name__ == __main__'блоку передаються на консоль.

Чи є спосіб змусити pytestвипускати реєстрацію на консоль також із методів тестування?


3
Ви можете поглянути на цю відповідь , опубліковану творцем py.test. Він пропонує плагін pytest, який забезпечує високий ступінь універсальності.
chb

Відповіді:


30

У мене працює, ось результат, який я отримую: [snip -> неправильний приклад]

Редагувати: Здається, вам потрібно передати -sопцію py.test, щоб вона не захопила stdout. Тут (py.test не встановлено), цього було досить для використання python pytest.py -s pyt.py.

Для вашого коду, все , що вам потрібно пройти -sв argsдо main:

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

Дивіться документацію py.test щодо збору вихідних даних .


Вибачте. Я вставив код поспіхом. Будь ласка, видаліть 'assert 0 == 1' з функції 'test_one', щоб помітити "проблему". Лише коли відбувається якась помилка (яку я змусив помилковим твердженням), py.test, здається, друкує інформацію про реєстрацію.
суперселектор

Немає проблем, я дізнався, як це виправити в командному рядку, шукаючи програмний спосіб.
TryPyPy

1
Ви також можете перенаправити вихідні дані журналу на якийсь файл замість неявного неявного stderr.
hpk42

@superselector hpk42 - py.test хлопець, послухай. IIUC, у вашому коді це буде logging.basicConfig(filename="somelog.txt", level=logging.DEBUG).
TryPyPy

115

Починаючи з версії 3.3, pytestпідтримується реєстрація в реальному часі, це означає, що всі записи журналу, випущені в тестах, будуть негайно надруковані на терміналі. Ця функція задокументована в розділі " Живі журнали ". Запис за умовчанням ведеться в режимі реального часу; щоб увімкнути його, встановіть log_cli = 1у pytest.iniконфігурації 1 . Реєстрація в режимі реального часу підтримує випромінювання в термінал і файл; відповідні параметри дозволяють налаштування записів:

термінал:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

файл:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

Примітка : log_cliпрапор не можна передавати з командного рядка, його потрібно встановити pytest.ini. Усі інші параметри можуть бути передані з командного рядка або встановлені у файлі конфігурації. Як зазначав Кевін Барре в цьому коментарі , перевизначення параметрів ini з командного рядка можна зробити за допомогою -o/--overrideопції. Таким чином , замість того , щоб оголосити log_cliв pytest.ini, ви можете просто зателефонувати:

$ pytest -o log_cli=true ...

Приклади

Простий тестовий файл, який використовується для демонстрації:

# 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

Як бачите, додаткової конфігурації не потрібно; pytestвстановить реєстратор автоматично на основі параметрів, зазначених у pytest.iniкомандному рядку або переданих з нього.

Реєстрація в реальному часі на термінал, INFOрівень, вигаданий вихід

Конфігурація в 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

Запуск тесту:

$ 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 =============================

Реєстрація в реальному часі на терміналі та у файлі, лише повідомлення та CRITICALрівень у терміналі, химерний вихід у pytest.logфайл

Конфігурація в 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

Тестовий запуск:

$ 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 Незважаючи на те, що ви можете налаштувати pytestв setup.cfgцьому [tool:pytest]розділі, не спокушайтеся це робити, коли ви хочете надати власний формат журналу. Інші інструменти для читання setup.cfgможуть сприймати такі речі як %(message)sінтерполяцію рядків та не вдаватися. Використовуйте, pytest.iniщоб уникнути помилок.


17
Щодо примітки, яка log_cliповинна бути в pytest.ini , здається, ви можете використовувати -oопцію, щоб замінити значення з командного рядка. pytest -o log_cli=true --log-cli-level=DEBUGпрацює для мене.
Кевін Барре,

@ KévinBarré дуже приємний коментар та дуже корисний підказка загалом, дякую! Відповідь оновлено.
hoefling

Це, безумовно, правильна відповідь при використанні журналів. Хоча мені подобається розрізняти журнали, що знаходяться всередині тестів, і журнали, що знаходяться всередині тестованої системи, які слід розглядати окремо.
CMCDragonkai,

@CMCDragonkai, на жаль, pytestдещо обмежений у цьому питанні. Однак це має бути здійснено за допомогою спеціальної конфігурації ведення журналу для тестів у вашому додатку; вимкніть розповсюдження у ваших реєстраторах та додайте "обробник тесту", який реєструється у вказаному файлі. Таким чином, pytestреєструються лише записи, що надходять із тестів, тоді як користувальницький обробник піклується про журнали SuT.
hoefling

1
@OfekAgmon, якщо ви хочете зберегти pytestвихідні дані, ви можете використовувати --result-logаргумент (хоча зверніть увагу, що він застарілий, ось альтернативи ). pytestОднак ви не можете зберігати вихідні дані та вихідний журнал в одному файлі.
hoefling
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.