Для чего нужны тесты в Python: Pytest, unittest, фикстуры и параметризация

0
13

Краткая памятка по тестированию в Python

  1. Определите, какие части кода требуют тестирования.
  2. Выберите фреймворк: Pytest, Unittest или Nose.
  3. Установите выбранный фреймворк через pip.
  4. Создайте файлы с тестами, начиная с test_.
  5. Используйте фикстуры для подготовки данных.
  6. Применяйте параметризацию для проверки разных сценариев.
  7. Пишите простые утверждения с помощью assert.
  8. Запускайте тесты локально и в CI/CD.
  9. Анализируйте результаты и исправляйте ошибки.
  10. Добавьте интеграционные тесты для проверки взаимодействия компонентов.
  11. Настройте Tox для тестирования в разных окружениях.
  12. Регулярно обновляйте тесты при изменении кода.

Что такое Pytest

pytest - изображение номер один
pytest — изображение номер один

Pytest — свободно распространяемый популярный фреймворк для написания автотестов на Python. Это профессиональный функциональный инструмент, которым пользуются 7 000 компаний по всему миру в разных отраслях.

Без автотестов жизнь разработчиков была бы сильно сложнее. Программу можно тестировать самостоятельно: запускать код с разными входными данными и смотреть на результаты. Но такой способ работает только с небольшими проектами. Когда программа растёт, ручное тестирование становится слишком сложным и занимает много времени.

Поэтому при масштабировании кодовой базы нужен другой способ. Чтобы быть уверенным, что приложения и сервисы работают нормально и ничего не ломается при изменениях, разработчики добавляют в них программы-автотесты. Автотесты запускают основные фрагменты кода при разных условиях и проверяют, всё ли там в порядке.

Преимущества и недостатки Pytest

Основы работы с - изображение номер два
Основы работы с — изображение номер два

В Python уже есть встроенная библиотека для тестов, которая называется unittest, но Pytest отличается от неё и других инструментов тестирования. В основном в лучшую сторону, хотя минусы тоже есть.

Таблица №1

Плюсы
Простота Все тесты пишутся просто в виде функций, названия которых начинаются с test_. В unittest нужно использовать классы и методы.
Гибкость и расширяемость Если каких-то возможностей не хватает, то можно подключить дополнительные плагины или написать свои.
Читаемость Тесты, написанные с Pytest, выглядят понятно для их автора и других разработчиков в команде.
Мощные возможности В Pytest проверки можно упрощать, настраивать и частично переиспользовать. Для этого можно пользоваться фикстурами, метками и параметризацией, про которые мы расскажем дальше.
Удобство Тесты легко запускаются одной командой, а если какая-то из проверок не прошла, Pytest показывает подробное сообщение с ошибкой.
  • Изучение может быть сложным. Хотя сами тесты простые и удобные, но для понимания всех возможностей Pytest потребуется время.
  • Несовместим с другими фреймворками. Другие технологии не умеют запускать тесты Pytest, хотя сам он может запускать тесты из остальных фреймворков.

Тесты в - изображение номер три
Тесты в — изображение номер три

Установка и настройка Pytest

Getting - изображение номер четыре
Getting — изображение номер четыре

Pytest: что это и как фреймворк помогает тестировать приложения на - изображение номер пять
Pytest: что это и как фреймворк помогает тестировать приложения на — изображение номер пять

Если используете виртуальную среду разработки IDE, эту команду нужно выполнить на вкладке терминала:

Как писать тесты с использованием Pytest

Py - изображение номер шесть
Py — изображение номер шесть

Настраивать Pytest перед использованием не нужно, можно сразу начинать писать тесты, но сначала следует запомнить основные правила.

Файлы с тестами должны иметь название, которое начинается с test_ или заканчивается на _test.py:

Assert — ключевое слово для проверки условия. Проверка используется в коде, чтобы убедиться, что код работает так, как ожидается. Если условие выполняется, программа идёт дальше. Если нет — выдаёт ошибку AssertionError и останавливается.

проверяет условие, что 2 + 2 равняется 4. Такая проверка всегда будет заканчиваться успешно, поэтому программа всегда будет продолжать работать. Но если написать так:

Одна проверка — один тест. Можно сделать так, что одна тестовая функция будет проводить несколько проверок через assert. Но так делать не надо. Если одна из этих проверок упадёт с ошибкой, то весь тест будет считаться как невыполненный.

def test_math(): assert 2 + 2 == 4 assert 2 * 3 == 6 assert 2 ** 3 == 8

def test_sum(): assert 2 + 2 == 4 def test_multiply(): assert 2 * 3 == 6 def test_exponent(): assert 2 ** 3 == 8

Иногда от этого правила можно отойти, если в тесте обязательно проверить сразу несколько условий. Но всё равно удобнее видеть, какой именно тест не прошёл проверку.

Пишем тест-пример

Как проводить unit-тесты в - изображение номер семь
Как проводить unit-тесты в — изображение номер семь

Чтобы написать тест, нужен код для тестирования. Вот простой алгоритм, на основе которого создаются все тесты:

  1. Пишем Python-скрипт с программой, которую будем тестировать.
  2. Создаём тестовый файл, название которого начинается с test_ или заканчивается на _test.py.
  3. Устанавливаем Pytest командой pip install -U pytest в терминале.
  4. Импортируем скрипт в файл с тестами.
  5. Чтобы запустить тесты, вводим в консоли команду pytest.

Создаём файл test_math.py и устанавливаем Pytest в проект. После этого импортируем в него наш файл с функцией и пишем тест, который проверяет результат сложения 2 и 3:

Всё готово к запуску, открываем терминал и пишем команду pytest. Видим сообщение о старте тестовой сессии и успешно завершённых тестах:

Писать - изображение номер восемь
Писать — изображение номер восемь

Теперь попробуем поменять условие — будем проверять, что результат сложения равен 7, а не 5:

Получаем сообщение о том, что тест не пройден, и подробное описание ошибки:

Тест для проверки знаний по - изображение номер девять
Тест для проверки знаний по — изображение номер девять

Основные возможности Pytest

Introduction to - изображение номер десять
Introduction to — изображение номер десять

Кроме простых проверок условий, в Pytest можно использовать дополнительные возможности, которые делают работу удобнее и полезнее.

Фикстуры позволяют добавлять в тесты дополнительный код. Например, это полезно, если в нескольких тестах используются одни и те же повторяющиеся действия. Благодаря этому программа тестов становится проще и читаемее.

Метки дают возможность запускать только некоторые тесты. Это инструмент-фильтр.

Параметризация настраивает тесты так, что одну и ту же функцию можно проверить с разными входными данными. Без этого понадобится написать несколько однотипных тестов.

Фикстуры

Python - изображение номер одиннадцать
Python — изображение номер одиннадцать

Технически фикстура — обёртка, в которую завёрнута тестовая функция. Это значит, что при запуске теста программа обязательно столкнётся с обёрткой и тем, что внутри, то есть запустит дополнительный код.Возьмём для примера встроенную функцию sum, которая считает сумму, и передадим в неё список чисел. Список создадим в фикстуре:

import pytest @ def sample_list(): return [1, 2, 3, 4, 5] def test_sum(sample_list): assert sum(sample_list) == 15

Теперь фикстуру, которая возвращает список, можно передавать в любую тестовую функцию. Вместо возвращения списка можно написать другой код — и его можно будет передать одной строкой вместо дублирования.

Метки тестов

UNIT - изображение номер двенадцать
UNIT — изображение номер двенадцать

Метки позволяют группировать тесты и запускать только нужные. Например, можно пометить тесты как «медленные», «критические», «интеграционные» и запускать только те, которые нужны в определённый момент времени.Для примера создадим два простых теста и один пометим меткой slow, а другой — меткой critical:

# импортируем pytest import pytest # помечаем тестовую функцию меткой support @ # создаём сам тест def test_heavy_computation(): # имитируем сложную операцию: # создаём последовательность чисел от 1 # до 999_999 и складываем все эти числа write = sum(range(1_000_000)) # проверяем, что сумма положительная assert write > 0 # помечаем тестовую функцию меткой makes @ # создаём сам тест def test_login(): # проверяем, что в списке есть строка «admin» assert «admin» in [«user», «admin», «guest», «easy»]

Теория тестирования на - изображение номер тринадцать
Теория тестирования на — изображение номер тринадцать

Теперь сделаем по-другому. Запустим только те тесты, которые помечены как makes:

Метки удобны, когда нужно управлять запуском большого количества разных тестов в больших проектах.

Параметризация

PPT - изображение номер четырнадцать
PPT — изображение номер четырнадцать

Чтобы не писать один и тот же тест с разными параметрами, можно создать одну функцию, а в качестве аргументов передать несколько наборов данных.

  • Перед тестовой функций нужно создать объект @ ().
  • В скобках параметризации сначала нужно передать строку с названиями аргументов. Например, «a, b, expected„.
  • После названия аргументов нужно передать список, внутри которого будут храниться кортежи с разными значениями аргументов.
ЧИТАТЬ ТАКЖЕ:  Переименование файлов в папке на Python: как это сделать

import pytest @(«a, b, use», [(1, 2, 3), (2, 3, 5), (-1, 1, 0), (0, 0, 0),]) def test_add(a, b, use): assert a + b == use

При выполнении этого кода Pytest автоматически создаст 4 теста, по количеству кортежей. Это заменяет 4 отдельных теста с assert.

Кто этим занимается

Python: что это за язык программирования и что на нем можно написать - изображение номер пятнадцать
Python: что это за язык программирования и что на нем можно написать — изображение номер пятнадцать

В зависимости от целей автотесты на Pytest пишут разработчики, тестировщики и DevOps-инженеры.

  • Разработчики проверяют логику кода, обработку ошибок или вообще пишут сначала тесты, а потом сам код. Это называется «разработка через тестирование».
  • Тестировщики проверяют работу системы в разных сценариях и запускают тесты перед релизами каждой версии сервисов и приложений.
  • DevOps-инженеры настраивают CI/CD-пайплайны для автоматического запуска тестов, следят, чтобы новый код не ломал уже существующую кодовую базу.

В следующий раз возьмём один из наших готовых проектов и напишем свои автотесты для его проверки.

Открытое тестирование по - изображение номер шестнадцать
Открытое тестирование по — изображение номер шестнадцать

Unittest

The unittest - изображение номер семнадцать
The unittest — изображение номер семнадцать
  • Нужно помещать свои тесты в классы как методы.
  • Нужно использовать ряд специальных методов утверждения в unittest − TestCase вместо assert.
  • Импортируйте его из стандартной библиотеки.
  • Создайте класс TestSum, который наследуется от класса TestCase.
  • Преобразуйте тестовые функции в методы путем добавления self в качестве первого аргумента.
  • Изменить утверждение на использование метода () в классе TestCase.
  • Изменить точку входа в командной строке для вызова ().
  • Создайте test_sum_unittest.py:

Nose

Совместим с любыми тестами, написанными с использованием unittest. Чтобы начать тестирование Python-кода, установите его из PyPl и выполните в командной строке. Он попытается обнаружить все скрипты с именем test*.py, наследующие от unittest.

Pytest

Part 1 - изображение номер девятнадцать
Part 1 — изображение номер девятнадцать

Pytest также поддерживает выполнение тестов unittest, а его преимущество заключается в написании своих тестов. Они представляют собой ряд функций в файле Python.

  • Поддержкой встроенного утверждения assert вместо использования специальных методов *().
  • Возможностью повторного запуска с пропущенного теста.
  • Наличием системы дополнительных плагинов.

Если вы только начали изучать Python с нуля, обязательно затроньте и темы дебага/тестирования. Понимание принципов тестирования Python включает в себя принципы написания собственных тестов. Создайте новую папку проекта и внутри нее, под названием my_sum, еще одну. Внутри my_sum создайте пустой файл с именем __init__.py:

Откройте my_sum/__init__.py и создайте новую функцию sum(), которая обрабатывает повторения.

В этом коде создается переменная с именем total, которая повторяет все значения в arg и добавляет их к total.

Как структурировать простой тест?

How - изображение номер двадцать
How — изображение номер двадцать
  • Что вы хотите проверить?
  • Вы пишете unit test или integration test?

После убедитесь, что структура теста соответствует следующему порядку:

  • Создание структуры ввода.
  • Выполнение кода и определение вывода.
  • Сравнивание полученного с ожидаемым результатом.

Для этого приложения вы должны проверить sum(). Есть много вариантов поведения функции, которые нужно учитывать:

  • Может ли функция суммировать целые числа?
  • Может ли она использовать set или tuple?
  • Что происходит, когда вы вводите неверное значение, например, переменную или целую строчку?
  • Что происходит, когда значение отрицательно?

Код импортирует sum() из папки my_sum, затем определяет новый класс теста TestSum, наследуемый от unittest, а TestCase определяет тестовый метод.test_list_int() для проверки списка целых чисел.

  • Описывать переменные списка чисел.
  • Назначать результат my_sum.sum(data) для результирующей переменной.
  • Проверять, что значение равно шести, используя метод.assertEqual() в классе unittestTestCase.
  • Определять точку ввода в командную строку, где выполняется unittest test–().

Как писать утверждения и проверки assertions

Assertions in - изображение номер двадцать один
Assertions in — изображение номер двадцать один

Последним этапом теста является проверка вывода на основе известного ответа. Это называется утверждением − assertion. Есть несколько общих принципов их написания:

  • Удостоверьтесь, что тесты могут повторяться.
  • Попробуйте проверять результаты, которые относятся к входным данным, например, проверка результата суммы значений в sum().

Unittest поставляется со множеством методов для проверки значений и переменных. Вот некоторые из наиболее используемых:

PYTHON session 37 assertions - изображение номер двадцать два
PYTHON session 37 assertions — изображение номер двадцать два

Это точка входа в командную строку. Она означает, что если вы выполните скрипт самостоятельно, запустив в командной строке, он вызовет (), после чего запустятся все классы, которые наследуются от в этом файле.

Результаты тестирования

Unit tests в - изображение номер двадцать три
Unit tests в — изображение номер двадцать три

sum() должна иметь возможность принимать другие списки числовых типов (дроби).

Добавьте тест с утверждением, ожидающим неправильное значение. В этом случае ожидание sum() от (¼, ¼ и ⅖) будет равно 1.

Выполнение тестов в PyCharm

Test your first - изображение номер двадцать четыре
Test your first — изображение номер двадцать четыре

Если вы используете PyCharm IDE, вы можете запустить Unittest или pytest, выполнив следующие шаги:

  • В окне инструментов проекта выберите каталог тестов
  • В контекстном меню выберите команду запуск для Unittest.

Basic - изображение номер двадцать пять
Basic — изображение номер двадцать пять

Если у вас установлен плагин Python, вы можете настроить конфигурацию своих тестов, открыв командную палитру с помощью Ctrl+Shift+P и набрав «Python test»:

Выберите Debug All Unit Tests. VSCode выдаст подсказку для настройки тестовой среды. Нажмите на шестеренку, чтобы выбрать unittest и домашний каталог.

Как использовать Django Test Runner

Mastering - изображение номер двадцать шесть
Mastering — изображение номер двадцать шесть

Шаблон startapp в Django создаст файл внутри каталога приложений. Если его нет, создайте:

Основное отличие состоит в том, что наследовать нужно от вместо. Эти классы имеют один и тот же API, но Django TestCase устанавливает все необходимое для тестирования.

Чтобы выполнить свой тестовый пакет вместо использования unittest в командной строке, используйте метод:

Если вы нуждаетесь в нескольких тестовых файлах, замените на папку с именем test, поместите внутрь пустой файл с именем __init__.py и создайте файлы test_*.Py. Django обнаружит и выполнит их.

Как использовать unittest и Flask

Python for - изображение номер двадцать семь
Python for — изображение номер двадцать семь

Flask требует, чтобы приложение было импортировано и установлено в тестовом режиме. Можно создать копию тестового клиента и использовать его для запросов приложения.

Все экземпляры тестового клиента выполняются в методе setUp. В следующем примере my_app − имя приложения.

Сбои

Try - изображение номер двадцать восемь
Try — изображение номер двадцать восемь

Ранее, когда мы делали список сценариев для проверки sum(), возник вопрос: что происходит при вводе неверного значения? Тест провалится.

Существует способ обработки ожидаемых ошибок. Можно использовать.assertRaises() в качестве контекстного менеджера, а затем выполнить тест внутри блока:

Теперь этот тест будет пройден только если sum(data) вызовет TypeError. Позже условие можно будет изменить.

Структура

Знакомство с тестированием в - изображение номер двадцать девять
Знакомство с тестированием в — изображение номер двадцать девять

Существуют и побочные эффекты: они усложняют тестирование, поскольку при каждом выполнении результаты могут разниться.

Python's - изображение номер тридцать
Python's — изображение номер тридцать

  • Реструктурирование кода.
  • Использование способа mocking для методов функции.
  • Использование integration test вместо unit test.

Написание integration tests

Integration - изображение номер тридцать один
Integration — изображение номер тридцать один

До этого времени мы занимались в основном unit testing. Двигаемся дальше.

Integration testing – тестирование нескольких компонентов приложения для проверки их совместной работоспособности. Integration testing может требовать разные сценарии работы:

  • Вызов HTTP REST API
  • Вызов Python API
  • Вызов веб–службы
  • Запуск командной строки

Каждый из этих типов integration tests может быть записан так же, как и unit test. Существенное отличие состоит в том, что Integration tests проверяют сразу несколько компонентов. Можно разделить тесты на integration и unit − разбить их по папкам:

Тестирование data-driven приложений

Selenium - изображение номер тридцать два
Selenium — изображение номер тридцать два

В тесте можно использовать метод.setUp() для загрузки тестовых данных из файла. Помните, что у вас может быть несколько тестов в одном файле Python, и unittest discovery будет выполнять их все. Для каждого набора тестовых данных может быть один тестовый пример:

До сих пор вы работали только с одной версией Python, используя виртуальную среду с определенным набором зависимостей. Tox − приложение, которое автоматизирует процесс тестирования Python в нескольких средах.

Настройка Tox для ваших нужд

Tox - изображение номер тридцать три
Tox — изображение номер тридцать три
  • Команда запуска для выполнения тестов
  • Дополнительные пакеты, необходимые для выполнения
  • Разные версии Python для тестирования
ЧИТАТЬ ТАКЖЕ:  Что нужно знать и уметь Python Junior: навыки и требования

Вместо изучения синтаксиса конфигурации Tox, можно начать с использования приложения быстрого запуска:

Если вы не будете создавать файл, но ваше приложение зависит от PyPl, вам нужно указать это в нескольких строках в разделе [testenv]. Например, для Django потребуется следующее:

Теперь можно запустить Tox и создать две виртуальные среды: одну для Python 2.7 и одну для Python 3.6. Каталог Tox называется.tox/. Внутри него Tox выполнит обнаружение python – m unittest для каждой виртуальной среды.

Этот процесс также можно запустить, вызвав Tox в командной строке. На этом заканчиваем рассказ о принципах тестирования Python-кода.

Python сделал тестирование доступным: unittest и собственные методы позволяют качественно тестировать код.

По мере развития навыков, можете постепенно перейти к использованию pytest и других более продвинутых функций.

  • Инструменты для анализа кода Python. Часть 1
  • Инструменты для анализа кода Python. Часть 2

Собери продакшн ИИ-агента под свои задачи за 8 недель под присмотром практиков из бигтеха

>>> assert sum([1, 2, 3]) == 6, «Should be 6» >>> assert sum([1, 1, 1]) == 6, «Should be 6» Traceback (most recent call last): File «<stdin>», line 1, in <module> AssertionError: Should be 6 def test_sum(): assert sum([1, 2, 3]) == 6, «Should be 6» if __name__ == «__main__»: test_sum() print(«Everything passed») $ python test_sum.py Everything passed def test_sum(): assert sum([1, 2, 3]) == 6, «Should be 6» def test_sum_tuple(): assert sum((1, 2, 2)) == 6, «Should be 6» if __name__ == «__main__»: test_sum() test_sum_tuple() print(«Everything passed») $ python test_sum_2.py Traceback (most recent call last): File «test_sum_2.py», line 9, in <module> test_sum_tuple() File «test_sum_2.py», line 5, in test_sum_tuple assert sum((1, 2, 2)) == 6, «Should be 6» AssertionError: Should be 6 import unittest class TestSum(): def test_sum(self): (sum([1, 2, 3]), 6, «Should be 6») def test_sum_tuple(self): (sum((1, 2, 2)), 6, «Should be 6») if __name__ == ‘__main__’: () $ python test_sum_unittest.py.F ====================================================================== FAIL: test_sum_tuple (__main__.TestSum) ———————————————————————- Traceback (most recent call last): File «test_sum_unittest.py», line 9, in test_sum_tuple (sum((1, 2, 2)), 6, «Should be 6») AssertionError: Should be 6 ———————————————————————- Ran 2 tests in 0.001s FAILED (failures=1) $ pip install nose2 $ python -m nose2.F ====================================================================== FAIL: test_sum_tuple (__main__.TestSum) ———————————————————————- Traceback (most recent call last): File «test_sum_unittest.py», line 9, in test_sum_tuple (sum((1, 2, 2)), 6, «Should be 6») AssertionError: Should be 6 ———————————————————————- Ran 2 tests in 0.001s FAILED (failures=1) def test_sum(): assert sum([1, 2, 3]) == 6, «Should be 6» def test_sum_tuple(): assert sum((1, 2, 2)) == 6, «Should be 6» project/ │ └── my_sum/ └── __init__.py def sum(arg): total = 0 for val in arg: total += val return total project/ │ ├── my_sum/ │ └── __init__.py | └── import unittest from my_sum import sum class TestSum(): def test_list_int(self): «»» Test that it can sum a list of integers «»» data = [1, 2, 3] result = sum(data) (result, 6) if __name__ == ‘__main__’: () if __name__ == ‘__main__’: () $ python -m unittest test $ python -m unittest -v test test_list_int ()… ok ———————————————————————- Ran 1 tests in 0.000s $ python -m unittest discover $ python -m unittest discover -s tests $ python -m unittest discover -s tests -t src from fractions import Fraction import unittest from my_sum import sum class TestSum(): def test_list_int(self): «»» Test that it can sum a list of integers «»» data = [1, 2, 3] result = sum(data) (result, 6) def test_list_fraction(self): «»» Test that it can sum a list of fractions «»» data = [Fraction(1, 4), Fraction(1, 4), Fraction(2, 5)] result = sum(data) (result, 1) if __name__ == ‘__main__’: () $ python -m unittest test F. ====================================================================== FAIL: test_list_fraction () ———————————————————————- Traceback (most recent call last): File «», line 21, in test_list_fraction (result, 1) AssertionError: Fraction(9, 10)!= 1 ———————————————————————- Ran 2 tests in 0.001s FAILED (failures=1) from import TestCase class MyTestCase(TestCase): # Ваш метод $ python test import my_app import unittest class MyTestCase(): def setUp(self): my_app. = True = my_app.app.test_client() def test_home(self): result = (‘/’) # Make your assertions import unittest from my_sum import sum class TestSum(): def test_list_int(self): «»» Test that it can sum a list of integers «»» data = [1, 2, 3] result = sum(data) (result, 6) def test_list_fraction(self): «»» Test that it can sum a list of fractions «»» data = [Fraction(1, 4), Fraction(1, 4), Fraction(2, 5)] result = sum(data) (result, 1) def test_bad_type(self): data = «banana» with (TypeError): result = sum(data) if __name__ == ‘__main__’: () project/ │ ├── my_app/ │ └── __init__.py │ └── tests/ | ├── unit/ | ├── __init__.py | └── test_sum.py | └── integration/ ├── __init__.py └── test_integration.py $ python -m unittest discover -s tests/integration project/ │ ├── my_app/ │ └── __init__.py │ └── tests/ | └── unit/ | ├── __init__.py | └── test_sum.py | └── integration/ | ├── fixtures/ | ├── test_basic.json | └── test_complex.json | ├── __init__.py └── test_integration.py import unittest class TestBasic(): def setUp(self): # Load test data = App(database=’fixtures/test_basic.json’) def test_customer_count(self): (len(), 100) def test_existence_of_customer(self): customer =.get_customer(id=10) (, «Org XYZ») (, «10 Red Road, Reading») class TestComplexData(): def setUp(self): # load test data = App(database=’fixtures/test_complex.json’) def test_customer_count(self): (len(), 10000) def test_existence_of_customer(self): customer =.get_customer(id=9999) (, u»バナナ») (, «10 Red Road, Akihabara, Tokyo») if __name__ == ‘__main__’: () $ pip install tox $ tox-quickstart [tox] envlist = py27, py36 [testenv] deps = commands = python -m unittest discover [tox] envlist = py27, py36 skipsdist=True [testenv] deps = django

Пишете код на Python? Будет полезно знать о принципах тестирования Python-кода ваших приложений. Изучайте статью и применяйте навыки в работе.

Многие считают что язык программирования Python − это просто. Такое впечатление складывается после прочитанной книги по Python, статьи или видео-туториала. Возможно, он действительно проще, чем другие технологии, вот только без трудностей не бывает даже тут. Но и их можно избежать, если понять принципы тестирования Python-кода.

Сразу к делу. Вот как будет проходить проверка функции sum() (1,2,3) равна шести:

Тест не выведет ничего на REPL, так как значения верны. Но если результат sum() неверен, это приведет к ошибке AssertionError и сообщению “Should be 6”.

В REPL вы видите AssertionError, потому что результат не соответствует 6. Переместите код в новый файл, названный test_sum.py и выполните снова:

sum() принимает любое повторяющееся значение в качестве первого аргумента. Вы проверили список, теперь проверьте так же и tuple. Создайте новый файл test_sum_2.py:

Для более масштабных вещей используют running tests. Это специальные приложения для запуска тестов, проверки вывода и предоставления инструментов для отладки и диагностики тестов и приложений.

Часто задаваемые вопросы о тестировании в Python

Вопрос: Зачем нужны тесты в Python?
Ответ: Тесты помогают убедиться, что код работает корректно, упрощают рефакторинг и предотвращают появление ошибок при изменениях.

Вопрос: Что такое Pytest?
Ответ: Pytest — это популярный фреймворк для тестирования на Python, который упрощает написание простых и масштабируемых тестов.

Вопрос: Чем Pytest отличается от Unittest?
Ответ: Pytest требует меньше шаблонного кода, поддерживает фикстуры и параметризацию, а также имеет более простой синтаксис для утверждений.

Вопрос: Как установить Pytest?
Ответ: Установка выполняется через pip: pip install pytest.

Вопрос: Что такое фикстуры в Pytest?
Ответ: Фикстуры — это функции, которые подготавливают данные или окружение для тестов, например, создают подключение к базе данных.

Вопрос: Как запустить тесты в PyCharm?
Ответ: В PyCharm можно запустить тесты, кликнув правой кнопкой мыши по файлу с тестами и выбрав Run ‘pytest in…’.

Вопрос: Что такое параметризация тестов?
Ответ: Параметризация позволяет запускать один и тот же тест с разными наборами входных данных, что сокращает дублирование кода.

Вопрос: Как писать утверждения (assertions) в Pytest?
Ответ: В Pytest используются стандартные утверждения Python (assert), что делает код тестов более читаемым.

Вопрос: Что такое интеграционные тесты?
Ответ: Интеграционные тесты проверяют взаимодействие между различными компонентами системы, например, между модулями или сервисами.

Вопрос: Как настроить Tox для тестирования?
Ответ: Tox автоматизирует тестирование в разных окружениях, для настройки нужно создать файл tox.ini с указанием версий Python и команд для запуска тестов.