Получить название текущего теста в настройке, используя нос
В настоящее время я пишу некоторые функциональные тесты, используя нос. Библиотека, которую я тестирую, управляет структурой каталогов.
Чтобы получить воспроизводимые результаты, я сохраняю шаблон структуры каталогов теста и создаю его копию перед выполнением теста (я делаю это внутри тестов setup
функция). Это гарантирует, что у меня всегда есть четко определенное состояние в начале теста.
Теперь у меня есть два дополнительных требования:
- Если тест не пройден, я бы хотел, чтобы структура каталогов, с которой он работал, не была перезаписана или удалена, чтобы я мог проанализировать проблему.
- Я хотел бы иметь возможность запускать несколько тестов параллельно.
Оба эти требования могут быть решены путем создания новой копии с другим именем для каждого выполняемого теста. По этой причине я хотел бы получить доступ к названию теста, который в настоящее время выполняется в setup
функция, так что я могу назвать копию соответствующим образом. Есть ли способ добиться этого?
Пример иллюстративного кода:
def setup_func(test_name):
print "Setup of " + test_name
def teardown_func(test_name):
print "Teardown of " + test_name
@with_setup(setup_func, teardown_func)
def test_one():
pass
@with_setup(setup_func, teardown_func)
def test_two():
pass
Ожидаемый результат:
Setup of test_one
Teardown of test_one
Setup of test_two
Teardown of test_two
Внедрение имени в качестве параметра было бы лучшим решением, но я открыт и для других предложений.
3 ответа
У меня есть решение, которое работает для тестовых функций, используя собственный декоратор:
def with_named_setup(setup=None, teardown=None):
def wrap(f):
return with_setup(
lambda: setup(f.__name__) if (setup is not None) else None,
lambda: teardown(f.__name__) if (teardown is not None) else None)(f)
return wrap
@with_named_setup(setup_func, teardown_func)
def test_one():
pass
@with_named_setup(setup_func, teardown_func)
def test_two():
pass
Это использует существующие with_setup
декоратор, но связывает имя оформленной функции с setup
а также teardown
функции передаются в качестве параметров.
Звучит как self._testMethodName
или self.id() должен работать для вас. Это свойство и метод на unittest.TestCase
учебный класс. Например:
from django.test import TestCase
class MyTestCase(TestCase):
def setUp(self):
print self._testMethodName
print self.id()
def test_one(self):
self.assertIsNone(1)
def test_two(self):
self.assertIsNone(2)
печатает:
...
AssertionError: 1 is not None
-------------------- >> begin captured stdout << ---------------------
test_one
path.MyTestCase.test_one
--------------------- >> end captured stdout << ----------------------
...
AssertionError: 2 is not None
-------------------- >> begin captured stdout << ---------------------
test_two
path.MyTestCase.test_two
--------------------- >> end captured stdout << ----------------------
Также см:
- Способ вывода имени теста pyunit в setup()
- Как получить имя запущенного тестового набора из testsuite в unittest
Надеюсь, это поможет.
В случае, если вы не хотите подкласс unittest.TestCase
или используйте собственный декоратор (как объяснено в других ответах), вы можете получить информацию, копаясь в стеке вызовов:
import inspect
def get_current_case():
'''
Get information about the currently running test case.
Returns the fully qualified name of the current test function
when called from within a test method, test function, setup or
teardown.
Raises ``RuntimeError`` if the current test case could not be
determined.
Tested on Python 2.7 and 3.3 - 3.6 with nose 1.3.7.
'''
for frame_info in inspect.stack():
if frame_info[1].endswith('unittest/case.py'):
return frame_info[0].f_locals['self'].id()
raise RuntimeError('Could not determine test case')