Как преобразовать юнит-тесты python в py.test при наличии глобальных фикстур?
У меня есть набор юнит-тестов, написанных с использованием модуля юнит-тестов python. Они используют функцию setUpModule() для загрузки глобальной переменной с общим "материалом", необходимым для выполнения тестов (включая некоторые http-сеансы).
Когда запустите мои тесты с unittest
они бегают py.test
они терпят неудачу.
Я немного исправил его, чтобы он работал с использованием старых функций фикстера pytest (которые, как оказалось, не имеют тех же имен, что и unittest). Работал, но только когда не выполняется в нескольких потоках, и это функция, которую я хочу использовать.
Примеры документации в моем случае бесполезны, потому что у меня есть около 20 классов (unittest.TestCase) с 10 тестами внутри каждого класса. Очевидно, я не хочу добавлять новый параметр в каждый тест.
До сих пор я использовал метод класса setUp(), чтобы загрузить общий словарь внутри себя и использовать его там внутри каждого теста.
#!/usr/bin/env python
# conftest.py
@pytest.fixture(scope="session")
def manager():
return { "a": "b"}
А теперь тесты:
#!/usr/bin/env python
# tests.py
class VersionTests(unittest.TestCase):
def setUp(self):
self.manager = manager
def test_create_version(self):
# do something with self.manager
pass
Пожалуйста, помните, что мне нужно решение, которое бы работало с несколькими потоками, вызывая фиксатор один раз.
1 ответ
pytest
может бежать unittest
проверяет наверняка, как описано в Поддержка для unittest.TestCase / Интеграция приборов. Сложность в том, что с помощью pytest
Приспособления funcargs напрямую не приветствуются:
Хотя pytest поддерживает получение осветителей через аргументы тестовой функции для методов тестирования, не относящихся к юнит-тесту, методы unittest.TestCase не могут напрямую получать аргументы функции фикстуры в качестве реализации, которая может повлиять на возможность запуска общих тестовых пакетов unittest.TestCase.
Предположим, у нас есть такой тестовый модуль, использующий стандарт unittest
средства инициализации:
# test_unittest_tests.py (for the sake of clarity!)
import unittest
manager = None
def setUpModule():
global manager
manager = {1: 2}
class UnittestTests(unittest.TestCase):
def setUp(self):
self.manager = manager
def test_1_in_manager(self):
assert 1 in self.manager
def test_a_in_manager(self):
assert 'a' in self.manager
Это дает следующий вывод при запуске с unittest
:
$ python -m unittest -v test_unittest_tests
...
test_1_in_manager (test_unittest_tests.UnittestTests) ... ok
test_a_in_manager (test_unittest_tests.UnittestTests) ... FAIL
...
test_a_in_manager
терпит неудачу, как и ожидалось, нет 'a'
ключ в manager
каталог.
Мы создали conftest.py, чтобы обеспечить область pytest
приспособления для этих испытаний. Как например, не нарушая стандарт unittest
поведение и без необходимости трогать их тесты вообще с помощью pytest
autouse:
# conftest.py
import pytest
@pytest.fixture(scope='session', autouse=True)
def manager_session(request):
# create a session-scoped manager
request.session.manager = {'a': 'b'}
@pytest.fixture(scope='module', autouse=True)
def manager_module(request):
# set the sessions-scoped manager to the tests module at hand
request.module.manager = request.session.manager
Выполнить тесты с pytest
(с помощью pytest-xdist
) для распараллеливания выдает следующий вывод:
$ py.test -v -n2
...
[gw1] PASSED test_unittest_tests.py:17: UnittestTests.test_a_in_manager
[gw0] FAILED test_unittest_tests.py:14: UnittestTests.test_1_in_manager
...
Теперь test_1_in_manager
вместо этого, нет 1
ключ в pytest
словарь менеджера.