Чуть больше про Pytest. Урок 2
Что разберем:
- Что такое предусловие, постусловие?
- Что такое фикстуры в pytest? Как мы можем их использовать?
- Какие аргументы принимают фикстуры?
- Зачем нужен yield в фикстурах?
- Что такое conftest.py файл?
- Что такое веб элемент?
- Какую информацию о веб элементе мы можем получить?
Предусловия, Постусловия Предлагаю немного углубиться в pytest и поговорить о фикстурах, но перед этим на нужно обратиться к теории тестирования.
В процессе тестирования очень важно привести систему в определенное состояние перед началом теста и вернуть ее в исходное или известное состояние после завершения теста. Эти действия обеспечивают повторяемость и надежность тестов.
Приведение системы в нужное состояние перед началом тестирования называется “Предусловие” (Precondition). Это набор условий или действий, которые должны быть выполнены или соблюдены перед началом исполнения тестового кейса. Возврат системы в исходное или известное состояние после тестирования называется “Постусловие” (Postcondition). Это то, что тестировщик делает после выполнения теста, чтобы вернуть систему в такое состояние, которое позволит другим тестам быть выполненными без остаточного влияния от предыдущего теста. Эти концепции особенно важны для автоматизированного тестирования, где тесты могут выполняться в произвольном порядке, и нам нужно быть уверенными в их независимости и повторяемости.
Предлагаю взглянуть на пример тест кейса использующего постусловие и предусловие
Тестовый кейс №: 001
Название: Добавление товара в корзину
Описание: Проверка функционала добавления товара в корзину на сайте интернет-магазина.
Предусловие:
Пользователь зарегистрирован и вошел в свой аккаунт.
Корзина пуста.
Товар в наличии.
Шаги:
Перейти на страницу товара.
Нажать "Добавить в корзину".
Открыть корзину.
Ожидаемый результат:
Товар отображается в корзине с правильным наименованием, ценой и количеством.
Постусловие:
Удалить товар из корзины.
Вернуть количество товара на склад (если применимо).
А теперь предлагаю взглянуть на вариант без постусловия и предусловия:
Тестовый кейс №: 002
Название: Изменение пароля пользователя
Описание: Проверка возможности смены пароля в профиле пользователя.
Шаги:
Войти в профиль пользователя.
Ввести новый пароль.
Подтвердить ввод нового пароля.
Ожидаемый результат:
Пользователь получает уведомление о том, что пароль успешно изменен.
Проблемы и последствия отсутствия предусловий и постусловий:
- Не заданное начальное состояние: Неясно, какой пользователь и какой у него изначальный пароль, что может привести к ошибкам при входе или использовании нецелевого аккаунта.
- Изменение состояния системы: После теста пароль пользователя изменен, что может нарушить другие тесты, использующие этот аккаунт. Влияние на реальные данные: Если тест проводится на реальных данных, это может влиять на реального пользователя, возможно, блокируя его доступ.
- Отсутствие отката: Без возвращения пароля к исходному состоянию тестовое окружение остается измененным, что может вызвать проблемы при последующем тестировании. Надеюсь, этот пример показывает важность предусловий и постусловий в тестировании.
Супер, мы разобрались что такое постусловие, предусловие и зачем же они нужны нам в тестировании.
Введение в фикстуры В документации Pytest мы можем найти страницу посвященную анатомии теста Ссылка: https://pytest.org/en/7.4.x/explanation/anatomy.html#test-anatomy
Предлагаю разобрать небольшой пример. Ссылка на пример в Github:
В файле registration_system.py находится класс имитирующий логику работы системы регистрации
Логика работы:
- Инициализация: При создании объекта этого класса инициализируется пустой словарь self.users. Этот словарь будет хранить информацию о пользователях. Ключом словаря является электронная почта пользователя, а значением - другой словарь с именем, номером телефона и email’ом.
- Регистрация пользователя: Метод register принимает имя, email и номер телефона пользователя. Если пользователь с указанным email уже существует в системе, метод возвращает ошибку. В противном случае, новый пользователь добавляется в систему, и метод возвращает успешное сообщение.
- Удаление всех пользователей: Метод delete_all_users очищает словарь self.users, удаляя всех пользователей из системы.
- Удаление пользователя по email: Метод delete_user_by_email принимает email пользователя, который необходимо удалить. Если такой пользователь существует, он удаляется из системы. Если пользователя с таким email нет, возвращается сообщение об ошибке.
- Просмотр всех пользователей: Метод view_all_users просто возвращает текущий словарь пользователей, позволяя просмотреть зарегистрированных пользователей.
В файле test_registration_system.py находится 2 теста с использованием pytest
Я подготовил ручные тест кейсы, которые впоследствии автоматизировал. Давайте сначала разберем ручные тесты:
Тестовый кейс №: 001
Название: Регистрация пользователя без предусловий и постусловий
Описание: Проверка функционала регистрации нового пользователя.
Шаги:
1.1 Создать объект класса RegistrationSystem.
1.2 Вызвать метод register с параметрами: "Алекс", "alex@example.com", "+1234567890".
1.3 Вызвать метод view_all_users и проверить наличие пользователя с данным email в системе.
Ожидаемый результат:
Пользователь с email "alex@example.com" присутствует в системе.
Теперь тест кейс с использованием предусловия и постусловия:
Тестовый кейс №: 002
Название: Регистрация пользователя с предусловиями и постусловиями
Описание: Проверка функционала регистрации нового пользователя с учетом начального состояния системы и восстановления исходного состояния после теста.
Предусловие:
Система инициализирована, база данных пуста.
Шаги:
2.1 Создать объект класса RegistrationSystem.
2.2 Вызвать метод register с параметрами: "Алекс", "alex@example.com", "+1234567890".
2.3 Вызвать метод view_all_users и проверить наличие пользователя с данным email в системе.
Ожидаемый результат:
Пользователь с email "alex@example.com" присутствует в системе.
Постусловие:
Удалить всех пользователей из системы, вызвав метод delete_all_users.
В первом тест кейсе мы просто добавляем пользователя и проверяем его наличие. Если вдруг был проведен еще какой-то тест до этого и он добавил пользователей в систему, это может повлиять на результат текущего теста, что делает его ненадежным.
Второй тест кейс начинает работу с чистой системой (предусловие) и в конце теста очищает систему (постусловие), гарантируя тем самым, что тест не будет влиять на последующие тесты и что результат теста будет всегда стабильным.
Теперь предлагаю разобрать код наших тестов
Данный код представляет собой набор тестов, написанных с использованием библиотеки pytest, для класса RegistrationSystem, который вы рассмотрели ранее. Основная цель тестов — проверить корректность регистрации новых пользователей в системе.
Импорты:
pytest: используется для написания и запуска тестов.
RegistrationSystem: основной класс из внешнего файла (registration_system.py), который мы будем тестировать.
Фикстура init_system: Фикстуры в pytest позволяют задавать начальные условия для тестов и выполнять некоторые операции после завершения теста. В данной фикстуре: Создается объект system класса RegistrationSystem. С помощью yield, этот объект передается тесту, который будет использовать фикстуру. После завершения теста (после строки с yield) выполняется метод delete_all_users(), который удаляет всех пользователей из системы. Это является постусловием, которое гарантирует, что после завершения теста система возвращается к исходному состоянию.
Тест test_registration_without_pre_post_conditions: В этом тесте: Создается новый объект system класса RegistrationSystem. Регистрируется новый пользователь с заданными данными. Проверяется наличие зарегистрированного пользователя в системе с помощью assert. Если условие не выполняется, тест будет считаться проваленным.
Тест test_registration_with_pre_post_conditions: В этом тесте: Используется фикстура init_system, чтобы получить объект системы с примененными предусловиями и постусловиями. Аналогично предыдущему тесту, регистрируется новый пользователь и проверяется его наличие в системе.
Логика работы: При запуске тестов с помощью pytest, оба тестовых метода будут выполнены. Перед запуском test_registration_with_pre_post_conditions будет выполнена фикстура init_system, инициализирующая систему. После завершения каждого теста, который использовал фикстуру, будет выполнено постусловие из фикстуры (очистка списка пользователей). Если какой-либо из assert утверждений не выполнится, pytest пометит соответствующий тест как проваленный. Ну вот наконец то мы дошли до фикстур давайте разберемся что же такое фикстуры, потренируемся в написании фикстур на более простом примере и вернемся к нашему коду с полным пониманием происходящего
Фикстуры в pytest - это мощный инструмент для настройки и очистки условий теста. Они позволяют определить и использовать тестовые ресурсы, такие как подключение к базе данных, создание временных файлов или предоставление конфигурационных данных для тестов. Фикстуры могут быть использованы для инициализации объектов или установки начальных условий перед запуском теста и для выполнения необходимой очистки после его завершения.
Определение фикстуры производится с помощью декоратора @pytest.fixture. Фикстуры можно затем внедрять в функции теста как аргументы. Давайте глянем на простой пример использования фикстуры
Пример так же можно найти в папке lesson2 -> в файле test_simple_example.py
Импорт необходимых библиотек: import pytest from faker import Faker
Здесь импортируются две библиотеки: pytest и Faker (для генерации фейковых данных). Определение фикстуры:
@pytest.fixture
def fake_email():
fake = Faker()
return fake.email()
@pytest.fixture - это декоратор из библиотеки pytest, который указывает, что следующая функция является фикстурой. Фикстуры в pytest используются для предоставления некоторых данных или состояний для тестов. Внутри фикстуры fake_email создается экземпляр объекта Faker (назовем его fake). С помощью метода fake.email() генерируется фейковый email. Фикстура возвращает сгенерированный фейковый email, который будет доступен для тестов, которые используют эту фикстуру.
Тестовая функция:
def test_email_format(fake_email):
# Проверка, что в email есть символ '@'
assert "@" in fake_email
# Проверка, что email содержит точку после символа '@'
assert "." in fake_email.split('@')[1]
# Проверка, что email не пустой
assert len(fake_email) > 0
Функция test_email_format является тестовой функцией, что видно по префиксу test_. Она принимает один аргумент, fake_email, который предоставляется фикстурой с тем же именем.
Внутри тестовой функции выполняются три проверки (assertions) для фейкового email:
- Проверяется наличие символа “@” в email.
- Проверяется наличие символа “.” в доменной части email (после символа “@”).
- Проверяется, что email не пустой. Если все проверки проходят без ошибок, то тест считается успешным.
Теперь предлагаю разобраться с тем какие аргументы может принимать фикстура и как это может помочь нам в работе
Аргументы фикстур в Pytest:
- autouse: Если аргумент autouse установлен в True, фикстура будет автоматически применена ко всем тестам, которые находятся в той же области видимости. Вам не нужно явно указывать фикстуру в аргументах теста. python
Пример в файле test_autouse_example.py. Когда мы используем autouse мы должны быть достаточно осторожны
scope: Аргумент scope определяет область видимости фикстуры: как часто она будет создана. Возможные значения: function (по умолчанию): Фикстура запускается для каждого теста отдельно. class: Фикстура запускается один раз для класса и используется для всех тестов внутри класса. module: Фикстура запускается один раз для модуля и используется для всех тестов внутри этого модуля. session: Фикстура запускается один раз за сессию и используется для всех тестов в течение этой сессии.
params — это ещё один важный атрибут для фикстур в pytest. Он позволяет параметризовать фикстуры. Это особенно полезно, когда вы хотите запустить один и тот же тест (или набор тестов) с разными начальными условиями или данными, предоставленными фикстурой.
yield в контексте pytest: В pytest, yield часто используется в фикстурах для разделения кода на часть, которая выполняется до тестов (секция “setup”), и часть, которая выполняется после тестов (секция “teardown”).
yield может передавать данные в тесты, когда используется в фикстурах pytest. Значение, которое передается через yield, будет передано тестовой функции как аргумент, если та принимает соответствующую фикстуру.
Что такое conftest.py файл? Зачем он нужен?
conftest.py — это специальный файл, используемый pytest, который содержит фикстуры и другие настройки, которые применяются к тестам на определенном уровне каталога. Это централизованное место для общих механизмов настройки тестов. Вот основные моменты, связанные с conftest.py:
- Область видимости: Фикстуры и конфигурации, определенные в conftest.py, автоматически доступны для всех тестовых файлов в том же каталоге и во всех подкаталогах.
- Порядок загрузки: Если есть несколько файлов conftest.py на разных уровнях в иерархии каталогов, pytest загрузит их все, начиная с самого верхнего уровня и заканчивая каталогом, в котором находятся тесты.
- Избегание импортов: Так как фикстуры в conftest.py автоматически доступны для всех тестов, вам не нужно импортировать их в каждом тестовом файле. Это делает код чище и упрощает масштабирование вашего тестового набора.
Веб-элемент в контексте Selenium — это представление элемента на веб-странице. Элементы на веб-странице могут включать в себя различные объекты, такие как кнопки, текстовые поля, изображения, гиперссылки, выпадающие списки и многие другие.
Какую информацию о веб элементе мы можем получить? https://www.selenium.dev/documentation/webdriver/elements/information/