Как преобразовать юнит-тесты 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 словарь менеджера.

Другие вопросы по тегам