В данной статье представлены примеры использования фикстур (fixture) в pytest.
Фикстуры в pytest представляют собой функции, которые можно использовать при автоматизации тестирования для решения следующих задач:
выполнение действий до проведения тестирования (например, настройка тестового окружения, создание тестовых данных, различные сетевые подключения, открытие файла и пр.);
выполнение действий после проведения тестирования (например, удаление временных данных, формирование отчета, отключение сетевых подключений, закрытие файлов и пр.);
вынос типовых действий в отдельные компоненты, что позволяет избежать дублирования кода и улучить его поддержку и читаемость;
корректно выполнять необходимые завершающие действия (финализация), даже в случаи ошибок в тестовых сценариях или при их прерывании.
Дисклеймер: В статье продемонстрированы синтетические примеры, наполненные методом print(), это сделано только для демонстрации последовательности выполнения шагов в stdout. При создании реальных тестовых кейсов рекомендуется использовать лучшие практики и паттерны программирования и проектирования, а также применяемые стандарты при разработке программного кода.
Оглавление
1. Введение
Для понимания как работают фикстуры в pytest необходимо:
умение работать с python;
умение работать с фреймворком для автоматизированного тестирования pytest;
знать, что в python всё является объектами;
принцип работы декоратора (@) для классов, функций и методов.
Фикстуры могут располагаться как внутри тестового файла, так и в отдельном файле (conftest.py). Для назначения фикстур используется декоратор "@pytest.fixture".
2. Обертки для тестовых объектов через фикстуры
Тестовые объекты можно обернуть в фикстуры, которые будут выполнять действия до и после тестового объекта.
![Обертки для тестовых объектов через фикстуры Обертки для тестовых объектов через фикстуры](https://habrastorage.org/getpro/habr/upload_files/d82/72b/bd0/d8272bbd0aae5be0342c51dec6a6a280.png)
import pytest
@pytest.fixture(scope='module', autouse=True)
def f_wrapper_module():
'''fixture: Обертка для тестового модуля'''
print('>', 'fixture: Запуск обертки для тестовго модуля')
yield
print('>', 'fixture: Завершение обертки для тестовго модуля')
@pytest.fixture(scope='class', autouse=True)
def f_wrapper_class():
'''fixture: Обертка для тестового класса'''
print('>>', 'fixture: Запуск обертки для тестовго класса')
yield
print('>>', 'fixture: Завершение обертки для тестовго класса')
@pytest.fixture(scope='function', autouse=True)
def f_wrapper_function():
'''fixture: Обертка для тестовой сессии'''
print('>>>', 'fixture: Запуск обертки для тестовой функции')
yield
print('>>>', 'fixture: Завершение обертки для тестовой функции')
class TestSuite1():
'''Первый testsuite'''
def test_1(self):
print('TestSuite1: Запуск test1')
assert True
def test_2(self):
print('TestSuite1: Запуск test2')
assert True
class TestSuite2():
'''Второй testsuite'''
def test_1(self):
print('TestSuite2: Запуск test1')
assert True
def test_2(self):
print('TestSuite2: Запуск test2')
assert True
Параметры в фикстуре:
"scope" - задает область работы fixture и может принимать следующие значения [ 'session' | 'package' | 'module' | 'class' | 'function' ]
"autouse" - автоматически включать данную fixture в область работы, без явного указания
Результат выполнения теста:
$: pytest -vs example.py
example.py::TestSuite1::test_1
> fixture: Запуск обертки для тестовго модуля
>> fixture: Запуск обертки для тестовго класса
>>> fixture: Запуск обертки для тестовой функции
TestSuite1: Запуск test1
PASSED
>>> fixture: Завершение обертки для тестовой функции
example.py::TestSuite1::test_2
>>> fixture: Запуск обертки для тестовой функции
TestSuite1: Запуск test2
PASSED
>>> fixture: Завершение обертки для тестовой функции
>> fixture: Завершение обертки для тестовго класса
example.py::TestSuite2::test_1
>> fixture: Запуск обертки для тестовго класса
>>> fixture: Запуск обертки для тестовой функции
TestSuite2: Запуск test1
PASSED
>>> fixture: Завершение обертки для тестовой функции
example.py::TestSuite2::test_2
>>> fixture: Запуск обертки для тестовой функции
TestSuite2: Запуск test2
PASSED
>>> fixture: Завершение обертки для тестовой функции
>> fixture: Завершение обертки для тестовго класса
> fixture: Завершение обертки для тестовго модуля
3. Передача объекта из фикстуры в тесты
Фикстуры можно использовать для передачи данных или объектов в тестовые сценарии, что позволяет упростить код и повысить его читаемость.
3.1 В тестовую функцию
![Передача объекта из фикстуры в тесты Передача объекта из фикстуры в тесты](https://habrastorage.org/getpro/habr/upload_files/399/a80/9d3/399a809d3be84ffbc0e2a03a88390358.png)
import pytest
@pytest.fixture()
def f_return_obj():
'''fixture: Возвращает объект'''
print('> fixture: Запуск f_return_obj()')
return 'объект из fixture'
def test_1(f_return_obj):
data = f_return_obj
print('test1: Объект из f_return_obj() -', data)
assert True
def test_2(f_return_obj):
data = f_return_obj
print('test2: Объект из f_return_obj() -', data)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
> fixture: Запуск f_return_obj()
test1: Объект из f_return_obj() - объект из fixture
PASSED
example.py::test_2
> fixture: Запуск f_return_obj()
test2: Объект из f_return_obj() - объект из fixture
PASSED
Также можно использовать одну фикстуру в других фикстурах:
![Использование одной фикстуры в другой Использование одной фикстуры в другой](https://habrastorage.org/getpro/habr/upload_files/48d/1db/b96/48d1dbb96a231661a097f5a8c2368f2e.png)
import pytest
@pytest.fixture()
def f_pre_return_obj_1():
'''fixture: Возвращает объект'''
print('>> fixture: Запуск f_pre_return_obj_1()')
return 'Объект из fixture 1'
@pytest.fixture()
def f_pre_return_obj_2():
'''fixture: Возвращает объект'''
print('>> fixture: Запуск f_pre_return_obj_2()')
return 'Объект из fixture 2'
@pytest.fixture()
def f_return_obj(f_pre_return_obj_1, f_pre_return_obj_2):
'''fixture: При вызове возвращает объект собранный из других fixture'''
print('> fixture: Запуск f_return_obj()')
return '{}, {}'.format(f_pre_return_obj_1, f_pre_return_obj_2)
def test_1(f_return_obj):
data = f_return_obj
print('test1: Объекты из f_return_obj() -', data)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
>> fixture: Запуск f_pre_return_obj_1()
>> fixture: Запуск f_pre_return_obj_2()
> fixture: Запуск f_return_obj()
test1: Объекты из f_return_obj() - Объект из fixture 1,
Объект из fixture 2
PASSED
Объект в тестовую функцию можно передать и с использованием фикстуры как обертки:
![Передача объекта в тестовую функцию через обертку фикстуры Передача объекта в тестовую функцию через обертку фикстуры](https://habrastorage.org/getpro/habr/upload_files/17f/b77/5a5/17fb775a5dd736b2fe3af5dba8109158.png)
import pytest
@pytest.fixture()
def f_wrapper_function():
'''fixture: Обертка для тестовой функции c передачей объекта'''
print('>>', 'fixture: Запуск обертки f_wrapper_function()')
var_fun = 'Значение объекта из f_wrapper_function()'
yield var_fun
print('>>', 'fixture: Завершение обертки f_wrapper_function()')
def test_1(f_wrapper_function):
data = f_wrapper_function
print('test1:', data)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
>> fixture: Запуск обертки f_wrapper_function()
test1: Значение объекта из f_wrapper_function()
PASSED
>> fixture: Завершение обертки f_wrapper_function()
3.2 В переменную тестового класса
![Фикстура назначает объект тестовому классу Фикстура назначает объект тестовому классу](https://habrastorage.org/getpro/habr/upload_files/ad0/818/0d3/ad08180d392378cebde1bbef72bec150.png)
import pytest
@pytest.fixture(scope='class', autouse=True)
def f_wrapper_class(request):
'''fixture: Обертка для тестового класса, которая также создает переменную'''
print('>', 'fixture: Запуск обертки f_wrapper_class()')
request.cls.var1 = 'var1: значение заданное fixture'
yield
print('>', 'fixture: Завершение обертки f_wrapper_class()')
@pytest.fixture(scope='class')
def f_set_var_in_class(request):
'''fixture: Задает тестовому классу переменную'''
print('>> fixture: Запуск f_set_var_in_class()')
request.cls.var2 = 'var2: значение заданное fixture'
@pytest.mark.usefixtures('f_set_var_in_class')
class TestSuite():
def test_1(self):
print('TestSuite: Запуск test1')
print('{}\n{}'.format(self.var1, self.var2))
self.var1 = 'var1: новое значение'
self.var2 = 'var2: новое значение'
print('{}\n{}'.format(self.var1, self.var2))
assert True
def test_2(self):
print('TestSuite: Запуск test2')
print('{}\n{}'.format(self.var1, self.var2))
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::TestSuite1::test_1
> fixture: Запуск обертки f_wrapper_class()
>> fixture: Запуск f_set_var_in_class()
TestSuite: Запуск test1
var1: значение заданное fixture
var2: значение заданное fixture
var1: новое значение
var2: новое значение
PASSED
example.py::TestSuite1::test_2
>> fixture: Запуск f_set_var_in_class()
TestSuite: Запуск test2
var1: значение заданное fixture
var2: значение заданное fixture
PASSED
> fixture: Завершение обертки f_wrapper_class()
! Обратите внимание, что при выполнении каждой тестовой функции, значения для переменных тестового класса остаются постоянными и равны значению заданного фикстурой. Примеры создания общего объекта с помощью фикстур для его использования в разных тестовых функциях представлен ниже.
4. Передача объекта между тестовыми функциями
Иногда возникает необходимость передавать один и тот же объект между разными тестовыми функциями.
4.1 Через отдельный независимый объект объект
![Использование независимого объекта для передачи данных Использование независимого объекта для передачи данных](https://habrastorage.org/getpro/habr/upload_files/e83/ddd/759/e83ddd75964ee760630540f8a68d3727.png)
Import pytest
class BDVar():
'''Класс для хранения переменных'''
def __init__(self, msg):
self.var = msg
def get_var(self):
return self.var
def set_var(self, new_var):
self.var = new_var
var = BDVar('var: значение по умолчанию')
@pytest.fixture(scope='class')
def f_wrapper_class():
'''fixture: Обертка для тестового класса, которая создает переменную'''
print('>', 'fixture: Запуск обертки f_wrapper_class()')
print(var.get_var())
var.set_var('var: значение заданное fixture')
print(var.get_var())
yield
print('>', 'fixture: Завершение обертки f_wrapper_class()')
@pytest.mark.usefixtures('f_wrapper_class')
class TestSuite():
def test_1(self):
print('TestSuite: Запуск test1')
print(var.get_var())
var.set_var('var: новое значение')
print(var.get_var())
assert True
def test_2(self):
print('TestSuite: Запуск test2')
print(var.get_var())
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::TestSuite::test_1
> fixture: Запуск обертки f_wrapper_class()
var: значение по умолчанию
var: значение заданное fixture
TestSuite: Запуск test1
var: значение заданное fixture
var: новое значение
PASSED
example.py::TestSuite::test_2
TestSuite: Запуск test2
var: новое значение
PASSED
> fixture: Завершение обертки f_wrapper_class()
4.2 Через отдельный объект внутри тестового класса
![Объект внутри тестового класса для хранения данных Объект внутри тестового класса для хранения данных](https://habrastorage.org/getpro/habr/upload_files/a92/ce3/002/a92ce30021db1b01e9ebd46bd72d2956.png)
import pytest
class BDVar():
'''Класс для хранения переменных'''
def __init__(self, msg):
self.var = msg
def get_var(self):
return self.var
def set_var(self, new_var):
self.var = new_var
@pytest.fixture(scope='class')
def f_wrapper_class(request):
'''fixture: Обертка для тестового класса, которая создает переменную'''
print('>', 'fixture: Запуск обертки f_wrapper_class()')
request.cls.var = BDVar('var: значение заданное fixture')
yield
print('>', 'fixture: Завершение обертки f_wrapper_class()')
@pytest.mark.usefixtures('f_wrapper_class')
class TestSuite():
def test_1(self):
print('TestSuite: Запуск test1')
print(self.var.get_var())
self.var.set_var('var: новое значение')
print(self.var.get_var())
assert True
def test_2(self):
print('TestSuite: Запуск test2')
print(self.var.get_var())
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::TestSuite1::test_1
> fixture: Запуск обертки f_wrapper_class()
TestSuite: Запуск test1
var: значение заданное fixture
var: новое значение
PASSED
example.py::TestSuite1::test_2
TestSuite: Запуск test2
var: новое значение
PASSED
> fixture: Завершение обертки f_wrapper_class()
5. Параметризация фикстур
Фикстуры как и обычные тестовые сценарии поддерживают возможность параметризации, что позволяет использовать один тестовый сценарий с различным набором параметров.
![Параметризации при использовании фикстур Параметризации при использовании фикстур](https://habrastorage.org/getpro/habr/upload_files/a46/2a2/bb2/a462a2bb210b21262209bea94a040810.png)
5.1 Через параметры в фикстуре
import pytest
@pytest.fixture(params=['параметр 1', 'параметр 2'])
def f_wrapper_function(request):
'''fixture: Возвращает объект'''
print('>', 'fixture: Запуск обертки f_wrapper_function()')
print('fixture: Создание объекта')
data = 'Объект из fixture: {}'.format(request.param)
yield data
print('fixture: Завершение созданного объекта')
print('>', 'fixture: Завершение обертки f_wrapper_function()')
def test_1(f_wrapper_function):
print('TestSuite: Запуск test1')
print(f_wrapper_function)
assert True
def test_2(f_wrapper_function):
print('TestSuite: Запуск test2')
print(f_wrapper_function)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1[параметр 1]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test1
Объект из fixture: параметр 1
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_1[параметр 2]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test1
Объект из fixture: параметр 2
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_2[параметр 1]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test2
Объект из fixture: параметр 1
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_2[параметр 2]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test2
Объект из fixture: параметр 2
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
5.2 Через mark.parametrize тестовой функции
import pytest
@pytest.fixture()
def f_wrapper_function(request):
'''fixture: Возвращает объект'''
print('>', 'fixture: Запуск обертки f_wrapper_function()')
print('fixture: Создание объекта')
data = 'Объект из fixture: {}'.format(request.param)
yield data
print('fixture: Завершение созданного объекта')
print('>', 'fixture: Завершение обертки f_wrapper_function()')
@pytest.mark.parametrize('f_wrapper_function', ('параметр 1', 'параметр 2'), indirect=True)
def test_1(f_wrapper_function):
print('TestSuite: Запуск test1')
print(f_wrapper_function)
assert True
@pytest.mark.parametrize('f_wrapper_function', ('параметр 3', 'параметр 4'), indirect=True)
def test_2(f_wrapper_function):
print('TestSuite: Запуск test2')
print(f_wrapper_function)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1[параметр 1]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test1
Объект из fixture: параметр 1
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_1[параметр 2]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test1
Объект из fixture: параметр 2
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_2[параметр 3]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test2
Объект из fixture: параметр 3
PASSED
fixture: Завершение созданного объекта
> fixture: Завершение обертки f_wrapper_function()
example.py::test_2[параметр 4]
> fixture: Запуск обертки f_wrapper_function()
fixture: Создание объекта
TestSuite: Запуск test2
Объект из fixture: параметр 4
PASSED
fixture: Завершение созданного объекта
>> fixture: Завершение обертки f_wrapper_function()
6. Передача параметров из тестовых сценариев в фикстуру для генерации на их основе объектов для выполнения тестов
Вынесения параметров которые используют фикстуры в тестовые сценарии позволяет создавать универсальные фикстуры и делать код более универсальным.
6.1 Через pytest.mark
![Применение pytest.mark Применение pytest.mark](https://habrastorage.org/getpro/habr/upload_files/ab9/e7c/1fe/ab9e7c1fef739d49685ec38dd4ee15cf.png)
import pytest
@pytest.fixture()
def f_cfg_obj(request):
'''fixture: Получает данные перед выполнением тестовой функции'''
print('>', 'fixture: Запуск f_set_obj()')
marker = request.node.get_closest_marker('f_data')
data = None if marker is None else marker.args[0]
print('fixture:', data)
return data.replace('Переданный', 'Измененый').replace('в', 'от')
@pytest.mark.f_data('Переданный параметр в fixture')
def test_1(f_cfg_obj):
print('test1:', f_cfg_obj)
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
> fixture: Запуск f_set_obj()
fixture: Переданный параметр в fixture
test1: Измененый параметр от fixture
PASSED
6.2 Через метод внутри fixture
![Взаимодействие с фикстурой через внутренний метод Взаимодействие с фикстурой через внутренний метод](https://habrastorage.org/getpro/habr/upload_files/b1f/c09/b34/b1fc09b34e6fe07c88067842bfbc56d2.png)
import pytest
@pytest.fixture()
def f_cfg_obj(request):
'''fixture: Через метод возвращает объект'''
print('>', 'fixture: Запуск f_set_obj()')
def _set_cfg(cfg):
print('>>', 'fixture: Запуск _set_cfg()')
return cfg.replace('переданный в', 'измененый от')
return _set_cfg
def test_1(f_cfg_obj):
data_1 = f_cfg_obj('переданный в fixture параметр-1')
data_2 = f_cfg_obj('переданный в fixture параметр-2')
print('test1:\n- {}\n- {}'.format(data_1, data_2))
assert True
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
> fixture: Запуск f_set_obj()
>> fixture: Запуск _set_cfg()
>> fixture: Запуск _set_cfg()
test1:
- измененый от fixture параметр-1
- измененый от fixture параметр-2
PASSED
6.3 Через отдельный объект внутри тестового класса
![Взаимодействие с объектом расположенного внутри тестового класса Взаимодействие с объектом расположенного внутри тестового класса](https://habrastorage.org/getpro/habr/upload_files/916/883/881/91688388129328845f269419170176b1.png)
import pytest
class BDVar():
'''Класс для хранения переменных'''
def __init__(self, msg):
self.var = msg
def get_var(self):
return self.var
def set_var(self, new_var):
self.var = new_var
@pytest.fixture(scope='class', autouse=True)
def f_wrapper_class(request):
'''fixture: Обертка для тестового класса, которая создает переменную'''
print('>', 'fixture: Запуск обертки f_wrapper_class()')
request.cls.var = BDVar('var: значение заданное fixture')
yield
print('>', 'fixture: Завершение обертки f_wrapper_class()')
@pytest.fixture()
def f_cfg_obj(request):
'''fixture: Получает объект из переменной класа перед выполнением тестовой функции'''
print('>>', 'fixture: Запуск f_set_obj')
print('fixture:', request.cls.var.get_var())
request.cls.var.set_var('var: новое значение заданное в fixture')
print('fixture:', request.cls.var.get_var())
class TestSuite():
def test_1(self):
print('TestSuite: Запуск test1')
print(self.var.get_var())
self.var.set_var('var: новое значение')
print(self.var.get_var())
assert True
def test_2(self, f_cfg_obj):
print('TestSuite: Запуск test2')
f_cfg_obj
print(self.var.get_var())
assert True
Результат выполнения теста:
$: pytest -vs example.py
example8.py::TestSuite::test_1
> fixture: Запуск обертки f_wrapper_class()
TestSuite: Запуск test1
var: значение заданное fixture
var: новое значение
PASSED
example8.py::TestSuite::test_2
>> fixture: Запуск f_set_obj
fixture: var: новое значение
fixture: var: новое значение заданное в fixture
TestSuite: Запуск test2
var: новое значение заданное в fixture
PASSED
> fixture: Завершение обертки f_wrapper_class()
7. Финализация
Тестирование можно разбить на следующие этапы:
выполнение действий, до проведения тестирования (создание тестовых пользователей, открытие сетевого подключения, открытие файла и пр.)
тестирование
выполнение действий, после проведения тестирования (удаление тестовых пользователей, закрытие сетевого подключения, закрытие файла и пр.)
Финализация позволяет корректно выполнить последний этап тестирования при ошибках в тестовых сценариях или остановки тестирования.
![Процесс выполнения тестовых сценариев Процесс выполнения тестовых сценариев](https://habrastorage.org/getpro/habr/upload_files/748/2ce/27d/7482ce27d7f35821ff4684b30e6c30f2.png)
7.1 Через обертку для тестовой функции
import pytest
@pytest.fixture()
def f_wrapper_function():
'''fixture: Обертка для тестовой функции, которая возвращает объект'''
print('>', 'fixture: Запуск обертки f_wrapper_function()')
print('- Создание объекта в fixture')
data = 'Объект из fixture'
yield data
print('- Завершение созданного объекта:', data)
print('>', 'fixture: Завершение обертки f_wrapper_function()')
def test_1(f_wrapper_function):
print('TestSuite: Запуск test1')
print('-', f_wrapper_function)
assert True
def test_2(f_wrapper_function):
print('TestSuite: Запуск test2')
print('-', f_wrapper_function)
assert False
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
> fixture: Запуск обертки f_wrapper_function()
- Создание объекта в fixture
TestSuite: Запуск test1
- Объект из fixture
PASSED
- Завершение созданного объекта: Объект из fixture
> fixture: Завершение обертки f_wrapper_function()
example.py::test_2
> fixture: Запуск обертки f_wrapper_function()
- Создание объекта в fixture
TestSuite: Запуск test2
- Объект из fixture
FAILED
- Завершение созданного объекта: Объект из fixture
> fixture: Завершение обертки f_wrapper_function()
7.2 Через метод внутри фикстуры с использованием addfinalizer
import pytest
@pytest.fixture(scope='function')
def f_return_obj(request):
'''fixture: Возвращает объект'''
print('>', 'fixture: Запуск f_return_obj()')
print('- Создание объекта в fixture')
data = 'Объект из fixture'
# Функция корректного завершения объекта
def del_object():
print('- Завершение созданного объекта:', data)
# Финализация
request.addfinalizer(del_object)
return data
def test_1(f_return_obj):
print('TestSuite: Запуск test1')
print('-', f_return_obj)
assert True
def test_2(f_return_obj):
print('TestSuite: Запуск test2')
print('-', f_return_obj)
assert False
Результат выполнения теста:
$: pytest -vs example.py
example.py::test_1
> fixture: Запуск f_return_obj()
- Создание объекта в fixture
TestSuite: Запуск test1
- Объект из fixture
PASSED
- Завершение созданного объекта: Объект из fixture
example.py::test_2
> fixture: Запуск f_return_obj()
- Создание объекта в fixture
TestSuite: Запуск test2
- Объект из fixture
FAILED
- Завершение созданного объекта: Объект из fixture
7.3 Через отдельный объект внутри класса
Если необходимо создать отдельный объект для класса и в конце его корректно завершить, то можно использовать следующий способ:
import pytest
class Сonnect():
'''Класс для соединения'''
def __init__(self, config):
self.cfg = config
self.status = 'Объект создан'
def get_cfg(self):
return self.cfg
def get_status(self):
return self.status
def set_status(self, new_status):
self.status = new_status
@pytest.fixture(scope='class')
def f_wrapper_class(request):
'''fixture: Обертка для тестового класса'''
print('>', 'fixture: Запуск обертки f_wrapper_class()')
print('- Создание объекта')
request.cls.connect = Сonnect('Параметры соединения')
print('- config (fixture):', request.cls.connect.get_cfg())
print('- status (fixture):', request.cls.connect.get_status())
request.cls.connect.set_status('Соединение установлено')
print('- status (fixture):', request.cls.connect.get_status())
yield
request.cls.connect.set_status('Соединение разорвано')
print('- status (fixture):', request.cls.connect.get_status())
print('>', 'fixture: Завершение обертки f_wrapper_class()')
@pytest.mark.usefixtures('f_wrapper_class')
class TestSuite():
def test_1(self):
print('TestSuite: Запуск test1')
print('- status (fun):', self.connect.get_status())
self.connect.set_status('Работа выполнена')
print('- status (fun):', self.connect.get_status())
assert True
def test_2(self):
print('TestSuite: Запуск test2')
print('\n- status (fun):', self.connect.get_status())
self.connect.set_status('В работе возникла ошибка')
print('- status (fun):', self.connect.get_status())
assert False
Результат выполнения теста:
$: pytest -vs example.py
example.py::TestSuite::test_1
> fixture: Запуск обертки f_wrapper_class()
- Создание объекта
- config (fixture): Параметры соединения
- status (fixture): Объект создан
- status (fixture): Соединение установлено
TestSuite: Запуск test1
- status (fun): Соединение установлено
- status (fun): Работа выполнена
PASSED
example.py::TestSuite::test_2
TestSuite: Запуск test2
- status (fun): Работа выполнена
- status (fun): В работе возникла ошибка
FAILED
- status (fixture): Соединение разорвано
> fixture: Завершение обертки f_wrapper_class()