В Python существует несколько инструментов и фреймворков для тестирования, наиболее популярные среди которых – unittest и pytest.
Содержание
- Важность тестирования
- Введение в unittest
- Введение в pytest
- Сравнение unittest и pytest
- Лучшие практики написания тестов
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ
1. Важность тестирования
Тестирование – основа создания устойчивого и надежного ПО. Оно включает написание кода, который проверяет работу другого кода. Почему тестирование важно?
- Раннее обнаружение ошибок: Тесты помогают выявить ошибки до того, как ПО попадет к пользователям, что снижает затраты на их исправление.
- Обеспечение качества кода: Автоматические тесты создают защиту, чтобы новые изменения не ломали существующий функционал.
- Облегчение рефакторинга: С набором тестов вы можете уверенно улучшать и изменять код.
- Документация: Тесты могут служить документом, показывая, как код должен использоваться и какое поведение от него ожидается.
2. Введение в unittest
Unittest – это встроенный модуль для тестирования в Python. Он подходит для тестирования как небольших, так и крупных проектов.
Написание тестов
Тесты создаются путем создания подкласса unittest.TestCase
. Каждый метод в этом классе представляет тест, и его название должно начинаться с “test”.
Пример:
import unittest # Функция для тестирования def add(a, b): return a + b # Класс теста class TestMathOperations(unittest.TestCase): def test_add(self): self.assertEqual(add(1, 2), 3) self.assertEqual(add(-1, 1), 0) self.assertEqual(add(-1, -1), -2) if __name__ == '__main__': unittest.main()
Результат:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
Объяснение:
TestMathOperations
– это класс, наследующийunittest.TestCase
.test_add
– метод, который проверяет функциюadd
.self.assertEqual
проверяет, соответствует ли результат ожидаемому значению.
Выполнение тестов
Для запуска тестов обычно используется командная строка:
python -m unittest test_module.py
Объяснение:
python -m unittest test_module.py
: запускает тесты, определенные в файлеtest_module.py
.
Подготовка тестовой среды
Фикстуры помогают подготовить и очистить среду для тестов. В unittest для этого можно использовать методы setUp
и tearDown
.
Пример:
class TestMathOperations(unittest.TestCase): def setUp(self): self.value = 10 def test_add(self): result = add(self.value, 5) self.assertEqual(result, 15) def tearDown(self): del self.value
Объяснение:
setUp
: запускается перед каждым тестом. Полезен для инициализации данных.tearDown
: запускается после каждого теста. Полезен для очистки.
Проверка условий
Unittest предоставляет методы для проверки различных условий, например:
assertEqual(a, b)
: проверяет, равны лиa
иb
.assertNotEqual(a, b)
: проверяет, чтоa
иb
не равны.assertTrue(x)
: проверяет, чтоx
истинно.assertFalse(x)
: проверяет, чтоx
ложно.assertRaises(exception)
: проверяет, вызывается ли исключение.
Пример:
def test_divide(self): with self.assertRaises(ZeroDivisionError): result = 1 / 0
3. Введение в pytest
Pytest – это сторонний фреймворк для тестирования, который дает больше гибкости и упрощает процесс тестирования по сравнению с unittest.
Написание тестов
В pytest тесты пишутся как отдельные функции, а не как методы внутри класса.
Пример:
import pytest def add(a, b): return a + b def test_add(): assert add(1, 2) == 3 assert add(-1, 1) == 0 assert add(-1, -1) == -2
Результат:
=================== test session starts ======================= collected 1 item test_module.py .. [100%] ==================== 1 passed in 0.01s =======================
Объяснение:
test_add()
: отдельная функция, которая тестирует функциюadd
с помощью простых утвержденийassert
.
Запуск тестов
Для запуска тестов с pytest используйте команду:
pytest test_module.py
Объяснение:
pytest test_module.py:
Запускает все тесты в файлеtest_module.py
.
Использование фикстур
Фикстуры в pytest помогают подготовить и очистить тестовую среду. Они создаются с помощью декоратора @pytest.fixture
.
Пример:
import pytest @pytest.fixture def sample_data(): return {'key': 'value'} def test_data(sample_data): assert sample_data['key'] == 'value'
Объяснение:
@pytest.fixture
: определяет фикстуру. Фикстураsample_data
предоставляет данные для тестовой функции.
Продвинутые возможности
- Параметризация: С помощью
@pytest.mark.parametrize
можно запускать тест с разными значениями.
Пример:
import pytest @pytest.mark.parametrize('a, b, expected', [ (1, 2, 3), (-1, 1, 0), (-1, -1, -2) ]) def test_add(a, b, expected): assert add(a, b) == expected
- Обнаружение тестов: В
pytest
автоматическое обнаружение тестов означает, что фреймворк может самостоятельно находить и запускать тесты без необходимости явно указывать каждый файл или функцию. Это достигается благодаря определённым соглашениям о наименовании и структуре каталогов.
4. Сравнение unittest и pytest
Оба инструмента, unittest
и pytest
, обладают своими уникальными преимуществами, но у каждого свои особенности:
unittest:
- Встроенный, не требует установки. Он доступен сразу после установки Python, что делает его удобным для начинающих.
- Организация тестов через классы. Каждый класс может наследовать от
unittest.TestCase
, что дает доступ к методам для проверки условий (например,assertEqual
,assertTrue
и др.). Это подходит для сложных тестовых наборов, где важно поддерживать структуру. - Требует больше кода и настроек. Написание тестов в
unittest
может потребовать больше кода, особенно для настройки и очистки тестовой среды.
pytest:
- Требуется установка через pip.
pytest
не входит в стандартную библиотеку и его нужно устанавливать отдельно с помощьюpip install pytest
. Однако установка простая и быстрая, что не создает больших проблем. - Тесты пишутся как функции, а не классы. Это упрощает процесс написания тестов и делает их более читаемыми. Например, вместо создания класса для тестирования можно просто определить функции с именем, начинающимся на
test_
. - Гибкий и требует меньше кода. Например, он поддерживает фикстуры, которые позволяют легко настраивать общие тестовые ресурсы. Также
pytest
предоставляет много встроенных функций, таких как параметризация тестов, что значительно упрощает создание комплексных тестов.
5. Лучшие практики написания тестов
1. Пишите понятные и краткие тесты:
Каждый тест должен проверять только один аспект функциональности. Понятные и краткие тесты легче читать и поддерживать. Кроме того, если тест не проходит, будет проще выявить причину сбоя, так как он проверяет только один сценарий. Это помогает избежать путаницы и ускоряет процесс отладки. Таким образом, придерживаясь принципа “один тест — одно утверждение”, мы повышаем качество и надежность тестирования.
2. Используйте описательные названия для тестов:
Называние функций тестов понятным и информативным образом — ключевой аспект написания качественных тестов. Это не только улучшает читаемость кода, но и помогает другим разработчикам (или вам самим в будущем) быстро понять, что именно проверяет каждый тест.
Пример:
def test_addition_of_two_positive_numbers(): assert add(2, 3) == 5
3. Тестируйте граничные случаи:
Написание тестов для крайних случаев и возможных сценариев сбоев — важная часть процесса тестирования. Эти тесты помогают убедиться, что ваш код правильно обрабатывает неожиданные или некорректные входные данные.
Пример:
def test_divide_by_zero(): with pytest.raises(ZeroDivisionError): result = 1 / 0
4. Избегайте тестирования деталей:
Сосредоточьтесь на тестировании функциональности, а не внутренних деталей реализации. Это позволит сохранять тесты актуальными даже при изменении различных деталей.
5. Грамотно используйте фикстуры:
Использование фикстур в тестах — это мощный способ настройки и очистки тестовой среды, который помогает сделать тесты более эффективными и структурированными.
Заключение
Сегодня мы рассмотрели основы тестирования в Python с помощью unittest
и pytest
. Вы узнали, как писать тесты, управлять фикстурами и использовать расширенные возможности pytest
. При выборе между unittest
и pytest
учитывайте потребности вашего проекта и свои предпочтения: если вам нужна строгая структура и встроенная поддержка, unittest
может быть идеальным выбором. Однако, если вы цените гибкость и простоту, pytest
предложит больше возможностей для удобной разработки тестов.
Перевод статьи «Day 48: Testing in Python».