Самые малоиспользуемые функции Pytest

Почему тестировщик не пригласил Pytest на свой день рождения? Потому что он боялся, что тесты падут и вечеринка закончится с ошибкой 404 — «Файл не найден»!

Pytest — это один из наиболее популярных фреймворков для написания тестов на Python. 

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

В этой статье мы рассмотрим топ малоизвестных, но полезных функций Pytest.

5f01a3b92315b82ac199a4d65c165b54.jpg

1. Множественный запуск тестов

Pytest позволяет запускать тесты несколько раз с использованием параметра --count. Это полезно в следующих сценариях:

  • Поиск непостоянных ошибок

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

  • Исследование производительности

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

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

Преимущества множественного запуска тестов для оценки производительности включают:

— Обнаружение непостоянных проблем 

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

— Сбор статистики

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

— Регрессионное тестирование производительности 

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

Пример использования множественного запуска тестов для оценки производительности:

pytest --count=10 performance_test.py

В данном случае, тест performance_test.py будет запущен 10 раз, и результаты будут анализироваться для выявления временных изменений в производительности. Это помогает убедиться, что наше программное обеспечение остается производительным даже при различных условиях и изменениях.

— Определение стабильности

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

pytest --count=100

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

Пример:

pytest --count=10 test_calculate.py

Эта команда выполнит тест test_calculate.py 10 раз и предоставит отчет о результатах каждого запуска.

2. Отчеты о покрытии кода

Pytest интегрируется с различными инструментами для анализа покрытия кода, такими как coverage.py. Отчеты о покрытии кода — это важный инструмент для:

  • Измерения качества наших тестов

    Они позволяют определить, какая часть нашего кода осталась непокрытой тестами.

  • Поиска «мертвого» кода

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

  • Оптимизации кода

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

pytest --cov=my_module

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

Пример:

pytest --cov=my_module tests/

Эта команда выполнит тесты из каталога tests/ и создаст отчет о покрытии для модуля my_module. Мы увидим, какие строки кода были покрыты тестами, а какие остались непокрытыми.

3. Параметризация тестов

Использование параметризации позволяет сократить дублирование кода и улучшить читаемость наших тестов. 

Мы можем использовать параметры для передачи разных входных данных в один и тот же тест:

import pytest

@pytest.mark.parametrize("input, expected", [(1, 2), (2, 4), (3, 6)])
def test_double(input, expected):
    assert double(input) == expected

Это позволяет вам определить только одну реализацию теста, вместо создания нескольких одинаковых кейсов.

Допустим, у нас есть функция validate_email, и мы хотим проверить ее с разными входными данными. Мы можем использовать параметризацию для этой цели.

Пример:

import pytest

@pytest.mark.parametrize("email, is_valid", [("test@example.com", True), ("invalid-email", False)])
def test_validate_email(email, is_valid):
    result = validate_email(email)
    assert result == is_valid

Эта команда выполнит тест test_validate_email с разными входными данными, проверяя, корректно ли функция validate_email определяет валидность email.

4. Фильтрация и запуск по маркерам

Пометка тестов с использованием декораторов и их последующий запуск по маркерам — это мощный способ организации и выборочного выполнения тестов:

import pytest

@pytest.mark.smoke
def test_smoke_test():
    assert some_function() == 42

Затем мы можем запустить только тесты, помеченные как smoke-тесты:

pytest -m smoke

Это удобно, когда у нас есть разные категории тестов, и мы хотим запускать их по отдельности.

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

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

5. Автоматическое обновление зависимостей

d325efddd4d80a271b554c4530e2a8ba.jpg

С помощью параметра --self-upgrade, Pytest позволяет автоматически обновлять сам фреймворк до последней версии. Это важно для:

  • Получения последних исправлений ошибок и новых функций.

  • Гарантии совместимости нашего кода с актуальной версией Pytest.

pytest --self-upgrade \

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

6. Использование параметров командной строки в тестах

С использованием фикстуры request, мы можем передавать параметры командной строки в наши тесты. Это полезно, когда наши тесты зависят от внешних данных:

def test_command_line_args(request):
    arg_value = request.config.getoption("--my-arg")
    assert some_function(arg_value) == expected_value

Запустим тест с параметром командной строки:

pytest --my-arg=42

Это дает нам гибкость в настройке тестов в зависимости от внешних условий.

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

Пример:

def test_calculate_tax():
    tax_rate = float(input("Введем ставку налога: "))
    income = 1000
    result = calculate_tax(income, tax_rate)
    assert result == income * tax_rate

В этом примере значение ставки налога вводится через командную строку при запуске теста.

Заключение

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

© Habrahabr.ru