0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<h3>Подготовка данных</h3>
1
<h3>Подготовка данных</h3>
2
<p>Представим, что мы разрабатываем библиотеку<a>pydash</a>и хотим протестировать её функции для обработки коллекций:</p>
2
<p>Представим, что мы разрабатываем библиотеку<a>pydash</a>и хотим протестировать её функции для обработки коллекций:</p>
3
<ul><li>includes()</li>
3
<ul><li>includes()</li>
4
<li>size()</li>
4
<li>size()</li>
5
<li>filter()</li>
5
<li>filter()</li>
6
<li>и другие (всего их около 20 штук)</li>
6
<li>и другие (всего их около 20 штук)</li>
7
</ul><p>Для работы этих функций нужна заранее подготовленная коллекция. Проще всего придумать одну, которая подойдёт для тестирования большинства или даже всех функций:</p>
7
</ul><p>Для работы этих функций нужна заранее подготовленная коллекция. Проще всего придумать одну, которая подойдёт для тестирования большинства или даже всех функций:</p>
8
<p>В примере выше видно, что в каждом тесте мы создаем одну и ту же коллекцию. А теперь представьте, что таких тестов несколько десятков - код начнёт кочевать из одного места в другое, порождая всё больше и больше копипасты.</p>
8
<p>В примере выше видно, что в каждом тесте мы создаем одну и ту же коллекцию. А теперь представьте, что таких тестов несколько десятков - код начнёт кочевать из одного места в другое, порождая всё больше и больше копипасты.</p>
9
<p>Самый простой способ избежать этого - вынести определение коллекции на уровень модуля, вне тестовых функций:</p>
9
<p>Самый простой способ избежать этого - вынести определение коллекции на уровень модуля, вне тестовых функций:</p>
10
<p>Это простое решение убирает ненужное дублирование. Но у него есть серьезный недостаток. Коллекция теперь глобальная переменная, а значит любой тест, который изменяет ее, делает ее непригодной для последующих тестов.</p>
10
<p>Это простое решение убирает ненужное дублирование. Но у него есть серьезный недостаток. Коллекция теперь глобальная переменная, а значит любой тест, который изменяет ее, делает ее непригодной для последующих тестов.</p>
11
<p>Но даже если бы наш код не мутировал данные, все равно у такого подхода есть слабые стороны. Представьте себе такой код:</p>
11
<p>Но даже если бы наш код не мутировал данные, все равно у такого подхода есть слабые стороны. Представьте себе такой код:</p>
12
<p>Подвох тут в том, что переменная now инициализируется один раз, во время загрузки модуля. Весь код, определённый на уровне модуля выполняется ровно один раз.</p>
12
<p>Подвох тут в том, что переменная now инициализируется один раз, во время загрузки модуля. Весь код, определённый на уровне модуля выполняется ровно один раз.</p>
13
<p>Почему это может быть проблемой? Код в тесте работает с понятием "сейчас" и рассчитывает на то, что "сейчас" это почти моментальный снимок данного момента времени. Но в примере выше, now начинает отставать от реального "сейчас" и чем больше тестов и чем они сложнее, тем большее отставание.</p>
13
<p>Почему это может быть проблемой? Код в тесте работает с понятием "сейчас" и рассчитывает на то, что "сейчас" это почти моментальный снимок данного момента времени. Но в примере выше, now начинает отставать от реального "сейчас" и чем больше тестов и чем они сложнее, тем большее отставание.</p>
14
<p>Для решения проблемы подготовки данных в pytest предлагается инструмент, который называется<strong>фикстуры</strong>. Ниже пример того, как создавать дату перед каждым тестом:</p>
14
<p>Для решения проблемы подготовки данных в pytest предлагается инструмент, который называется<strong>фикстуры</strong>. Ниже пример того, как создавать дату перед каждым тестом:</p>
15
<p>Чтобы создать фикстуру, нам нужно описать функцию, которая подготавливает наши данные и обернуть ее декоратором @pytest.fixture. А для использования, ее нужно передать в параметры теста.</p>
15
<p>Чтобы создать фикстуру, нам нужно описать функцию, которая подготавливает наши данные и обернуть ее декоратором @pytest.fixture. А для использования, ее нужно передать в параметры теста.</p>
16
<p>Основное назначение фикстур - подготовка независимых данных. По умолчанию фикстура создается на каждый тест заново, что и гарантирует разделение тестов.</p>
16
<p>Основное назначение фикстур - подготовка независимых данных. По умолчанию фикстура создается на каждый тест заново, что и гарантирует разделение тестов.</p>
17
<p>Тесты могут использовать сколько угодно фикстур. Да и сами фикстуры могут использовать другие фикстуры, точно также через передачу в параметры.</p>
17
<p>Тесты могут использовать сколько угодно фикстур. Да и сами фикстуры могут использовать другие фикстуры, точно также через передачу в параметры.</p>
18
<p>Помимо явной передачи в параметры теста можно задать "автоиспользование" фикстуры, указав параметр autouse=True. Такая фикстура будет автоматически использоваться всеми тестами без ее указания.</p>
18
<p>Помимо явной передачи в параметры теста можно задать "автоиспользование" фикстуры, указав параметр autouse=True. Такая фикстура будет автоматически использоваться всеми тестами без ее указания.</p>
19
<p>Автоиспользование фикстур применяется для подготовки внешних сервисов, тестовых серверов или баз данных.</p>
19
<p>Автоиспользование фикстур применяется для подготовки внешних сервисов, тестовых серверов или баз данных.</p>
20
<h3>Области видимости</h3>
20
<h3>Области видимости</h3>
21
<p>Зачастую подготовка данных включает в себя более сложные действия, чем создание коллекции. Например, создать тестовый сервер, подключиться к базе данных и заполнить ее данными или создать пользователя через форму регистрации на сайте. Если производить эти операции перед каждым тестом, то это потребует больших затрат времени и памяти. Для решения этой проблемы у фикстур есть области видимости,<strong>scopes</strong>.</p>
21
<p>Зачастую подготовка данных включает в себя более сложные действия, чем создание коллекции. Например, создать тестовый сервер, подключиться к базе данных и заполнить ее данными или создать пользователя через форму регистрации на сайте. Если производить эти операции перед каждым тестом, то это потребует больших затрат времени и памяти. Для решения этой проблемы у фикстур есть области видимости,<strong>scopes</strong>.</p>
22
<p>По умолчанию, у фикстур задана область видимости function, то есть фикстура создается на каждую функцию, которая ее использует, и уничтожается при ее выполнении. Но есть и другие области:</p>
22
<p>По умолчанию, у фикстур задана область видимости function, то есть фикстура создается на каждую функцию, которая ее использует, и уничтожается при ее выполнении. Но есть и другие области:</p>
23
<ul><li>class - фикстура существует на весь класс с тестом</li>
23
<ul><li>class - фикстура существует на весь класс с тестом</li>
24
<li>module - фикстура существует на весь модуль</li>
24
<li>module - фикстура существует на весь модуль</li>
25
<li>package - фикстура существует на весь пакет с тестами</li>
25
<li>package - фикстура существует на весь пакет с тестами</li>
26
<li>session - фикстура существует на всю тестовую сессию</li>
26
<li>session - фикстура существует на всю тестовую сессию</li>
27
</ul><p>Так, например, подготовка тестовой базы данных, которая нам нужна на протяжении всей тестовой сессии, может выглядеть как:</p>
27
</ul><p>Так, например, подготовка тестовой базы данных, которая нам нужна на протяжении всей тестовой сессии, может выглядеть как:</p>
28
<h3>Совместные фикстуры</h3>
28
<h3>Совместные фикстуры</h3>
29
<p>Помимо указания области видимости, pytest также позволяет создавать фикстуры, которые можно использовать во всех модулях. Для этого их нужно прописать в файле<em>conftest.py</em>. Все фикстуры, определенные в нем, могут быть использованы любым тестом в директории<em>tests</em>без необходимости их импортировать, pytest обнаружит их автоматически.</p>
29
<p>Помимо указания области видимости, pytest также позволяет создавать фикстуры, которые можно использовать во всех модулях. Для этого их нужно прописать в файле<em>conftest.py</em>. Все фикстуры, определенные в нем, могут быть использованы любым тестом в директории<em>tests</em>без необходимости их импортировать, pytest обнаружит их автоматически.</p>
30
<p>Часто это требуется для подготовки данных, которые потребуются на протяжении всего тестирования - пользовательские сессии, соединения с базой данных, запуск внешних "тяжелых" сервисов.</p>
30
<p>Часто это требуется для подготовки данных, которые потребуются на протяжении всего тестирования - пользовательские сессии, соединения с базой данных, запуск внешних "тяжелых" сервисов.</p>
31
<h3>Очистка данных</h3>
31
<h3>Очистка данных</h3>
32
<p>В общем случае нам не нужно управлять очисткой данных, после завершения тестов, pytest самостоятельно удалит все фикстуры, очистив состояние после себя. Но иногда очистка может включать в себя освобождение каких-то ресурсов: закрытие файлов, возврат базы в изначальное состояние и прочие операции, обратные подготовке. Для этого в pytest существует выражение yield.</p>
32
<p>В общем случае нам не нужно управлять очисткой данных, после завершения тестов, pytest самостоятельно удалит все фикстуры, очистив состояние после себя. Но иногда очистка может включать в себя освобождение каких-то ресурсов: закрытие файлов, возврат базы в изначальное состояние и прочие операции, обратные подготовке. Для этого в pytest существует выражение yield.</p>
33
<p>Основные различия, что в коде return заменяется на yield и любой код очистки ресурсов помещается после yield. После выполнения тестов pytest пройдется по фикстурам и выполнит очистку данных.</p>
33
<p>Основные различия, что в коде return заменяется на yield и любой код очистки ресурсов помещается после yield. После выполнения тестов pytest пройдется по фикстурам и выполнит очистку данных.</p>
34
<p>Помните, что мы все еще работаем с компьютером и не застрахованы от поломок. Ошибка в неподходящем месте может оставить нашу систему в нестабильном состоянии, которое отразится на последующих тестах. Создавая фикстуры, лучше ограничивать каждую лишь одним действием, изменяющим состояние. Например, если процесс регистрации пользователя состоит из этапов создания базы, записи пользователя в базу и отправки письма, то правильно будет разделить эти этапы на отдельные фикстуры со своей подготовкой и очисткой.</p>
34
<p>Помните, что мы все еще работаем с компьютером и не застрахованы от поломок. Ошибка в неподходящем месте может оставить нашу систему в нестабильном состоянии, которое отразится на последующих тестах. Создавая фикстуры, лучше ограничивать каждую лишь одним действием, изменяющим состояние. Например, если процесс регистрации пользователя состоит из этапов создания базы, записи пользователя в базу и отправки письма, то правильно будет разделить эти этапы на отдельные фикстуры со своей подготовкой и очисткой.</p>
35
<h3>Встроенные фикстуры</h3>
35
<h3>Встроенные фикстуры</h3>
36
<p>В программировании часто приходится решать типовые задачи, уже не раз решенные раньше. Потому мы переиспользуем код, устанавливаем готовые библиотеки и применяем шаблоны. Pytest для частых задач предоставляет<a>встроенные фикстуры</a>. Среди них фикстуры для работы с временными директориями, кэшем или выводом в консоль. Чтобы их использовать, достаточно импортировать в тестах библиотеку pytest - встроенные фикстуры будут доступны сразу.</p>
36
<p>В программировании часто приходится решать типовые задачи, уже не раз решенные раньше. Потому мы переиспользуем код, устанавливаем готовые библиотеки и применяем шаблоны. Pytest для частых задач предоставляет<a>встроенные фикстуры</a>. Среди них фикстуры для работы с временными директориями, кэшем или выводом в консоль. Чтобы их использовать, достаточно импортировать в тестах библиотеку pytest - встроенные фикстуры будут доступны сразу.</p>
37
<h3>Выводы</h3>
37
<h3>Выводы</h3>
38
<p>Мы научились использовать инструмент подготовки данных - фикстуры. Узнали как создавать независимые данные для каждого теста, как использовать данные на протяжении разной длины тестирования и как их переиспользовать. Познакомились со встроенными фикстурами для типовых задач, а также узнали, как очистить результаты работы тестов и вернуть начальное состояние программы.</p>
38
<p>Мы научились использовать инструмент подготовки данных - фикстуры. Узнали как создавать независимые данные для каждого теста, как использовать данные на протяжении разной длины тестирования и как их переиспользовать. Познакомились со встроенными фикстурами для типовых задач, а также узнали, как очистить результаты работы тестов и вернуть начальное состояние программы.</p>