Тестирование на Python: unittest и pytest

В Python существует несколько инструментов и фреймворков для тестирования, наиболее популярные среди которых – unittest и pytest.

Содержание

  1. Важность тестирования
  2. Введение в unittest
  3. Введение в pytest
  4. Сравнение unittest и pytest
  5. Лучшие практики написания тестов
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ

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, что дает доступ к методам для проверки условий (например, assertEqualassertTrue и др.). Это подходит для сложных тестовых наборов, где важно поддерживать структуру.
  • Требует больше кода и настроек. Написание тестов в 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».

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *