HTML Diff
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>