Pytest: как получить имя файла/функции исполняемого теста?
Есть три файла: preconditions.py (тут я описываю поведение ДО и ПОСЛЕ прогона теста), conftest.py (тут я делаю фикстуру из прекондишенов) и непосредственно файл теста. Пример кода будет внизу. Суть в следующем. Я хочу в прекондишены засунуть лог, где будет писаться нечто в стиле "Старт теста: <ИМЯ ФАЙЛА/ИМЯ ФУНКЦИИ ТЕСТА>". Как я могу получить имя файла/функции запущенного теста? Я пытался использовать inspect: inspect.getmodule(inspect.stack()[1][0]).__file__)
Но столкнулся с тем, что данная конструкция выдаёт мне имя файла conftest.py, а не тест. Я менял индексы (в частности первый с 1 на 2), но получил в итоге только имя файла fixtures.py. А вот как получить имя конкретно имя теста в том или ином виде я так и не пришёл. Может кто-то помочь с этим? Или указать мне на ошибку.
Примеры кода:
preconditions.py
class Preconditions:
@classmethod
def setUp(cls):
# SOME CODE BEFORRE TESTS EXECUTION
pass
def tearDown(self):
# SOME CODE AFTER TESTS EXECUTION
pass
conftest.py
import pytest
from preconditions import Preconditions
@pytest.fixture(scope='module')
def testPreconditions():
execution = Preconditions.setUp()
binaries = Preconditions()
yield
binaries.tearDown()
test_some_name.py
import pytest
@pytest.mark.usefixtures('testPreconditions')
def test_some_name():
# SOME TEST-CASE CODE
pass
Ответы (1 шт):
Получить метаданные текущего теста можно с помощью фикстуры request. Пример:
import pytest
@pytest.fixture
def preconditions(request):
print("test case ID:", request.node.nodeid)
print("test case name:", request.node.name)
print("test module name:", request.node.module.__name__)
print("test file:", request.fspath)
yield
@pytest.mark.usefixtures('preconditions')
def test_some_name():
pass
Проблема в твоем примере в scope='module'. Эта фикстура будет выполняться только один раз на файл, не предоставляя информации о текущем тесте (потому что тесты из файла еще не стартовали). Измени scope='module' на scope='function' или просто убери параметр из декоратора.
Насчет конструкта с Preconditions: логгирование можно спокойно вести в самой фикстуре, не вынося его в отдельный класс. Но если наличие Preconditions является обязательным условием, то можно переписать код примерно следующим образом:
@pytest.fixture(scope="module")
def preconditions():
binaries = Preconditions()
binaries.setUp()
yield preconditions
binaries.tearDown()
Эта фикстура будет вызываться один раз на каждый файл, создавая и возвращая инстанс Preconditions, который затем можно использовать в фикстуре log, которая вызывается для каждого теста:
@pytest.fixture
def log(request, preconditions):
preconditions.trace(f"started test case {request.node.name}") # например
yield
preconditions.trace(f"finished test case {request.node.name}")
@pytest.mark.usefixtures("log")
def test_some_name():
pass