Эффективное тестирование Python с Pytest

15 мая, 2020

Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python. Там выходят задачи, полезные советы и сливы платных курсов - перейти
  • Как установить pytest
  • Что делает Pytest таким полезным?
    • Меньше Boilerplate
    • Управление состоянием и зависимостями
    • Тестовая фильтрация
    • Тест Параметризация
    • Архитектура на основе плагинов
  • Фикстуры: управление состоянием и зависимостями
    • Когда создавать фикстуры
    • Когда следует избегать приспособлений
    • Фикстуры в масштабе
  • Оценки: классификация тестов
  • Параметризация: комбинированные тесты
  • Отчеты о продолжительности: боевые медленные тесты
  • Полезные плагины Pytest
    • pytest-randomly
    • pytest-cov
    • pytest-django
    • pytest-bdd
  • Вывод

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

В этом уроке вы узнаете:

  • Какие преимущества pytest предлагает
  • Как убедиться, что ваши тесты не имеют состояния
  • Как сделать повторяющиеся тесты более понятными
  • Как запустить поднаборы тестов по имени или пользовательским группам
  • Как создать и поддерживать повторно используемые утилиты тестирования

Как установить pytest

Чтобы следовать примерам из этого руководства, вам необходимо установить pytest. Как и в большинстве пакетов Python, вы можете установить pytest в виртуальной среде из PyPI, используя pip:

$ python -m pip install pytest

Команда pytest теперь будет доступна в вашей среде установки.

Что делает pytest полезным?

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

Ряд сторонних платформ тестирования пытаются решить некоторые из проблем unittest, и pytest оказался одним из самых популярных . pytest это многофункциональная, основанная на плагинах экосистема для тестирования вашего кода Python.

Его философия и особенности сделают ваш опыт тестирования более продуктивным и приятным. При этом для выполнения pytest общих задач требуется меньше кода, а сложные задачи можно выполнить с помощью различных экономящих время команд и плагинов. Он даже запустит ваши существующие тесты из коробки, включая те, которые написаны с unittest.

Как и в случае с большинством фреймворков, некоторые шаблоны разработки, которые имеют смысл, когда вы впервые начинаете использовать pytest , могут начать появляться проблемы по мере роста вашего набора тестов. Этот учебник поможет вам понять некоторые из pytest инструментов  обеспечивающих эффективность и результативность тестирования даже при его масштабировании.

Меньше Boilerplate

Большинство функциональных тестов следуют модели Arrange-Act-Assert:

  1. Организовать или установить условия для теста
  2. Действовать, вызывая некоторую функцию или метод
  3. Утверждать, что некоторое конечное условие верно

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

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

# test_with_unittest.py

from unittest import TestCase

class TryTesting(TestCase):
    def test_always_passes(self):
        self.assertTrue(True)

    def test_always_fails(self):
        self.assertTrue(False)

Затем вы можете запустить эти тесты из командной строки, используя discover параметр unittest:

$ python -m unittest discover
F.
============================================================
FAIL: test_always_fails (test_with_unittest.TryTesting)
------------------------------------------------------------
Traceback (most recent call last):
  File "/.../test_with_unittest.py", line 9, in test_always_fails
    self.assertTrue(False)
AssertionError: False is not True

------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

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

  1. Импортировать TestCase класс из unittest
  2. Создать TryTesting, и подкласс изTestCase
  3. Написать метод TryTesting для каждого теста
  4. Использовать один из self.assert* методов из unittest.TestCase , чтобы сделать утверждения

Это значительное количество кода для написания, и, поскольку это минимум, необходимый для любого теста, в конечном итоге вы будете писать один и тот же код снова и снова. pytest упрощает этот рабочий процесс, позволяя вам напрямую использовать ключевое слово Python assert  :

# test_with_pytest.py

def test_always_passes():
    assert True

def test_always_fails():
    assert False

Вот и все. Вам не нужно иметь дело с импортом или классами. Поскольку вы можете использовать ключевое слово assert , вам также не нужно изучать или запоминать все различные self.assert* методы unittest. Если вы можете написать выражение, от которого вы ожидаете True, то pytest протестируете его для вас. Вы можете запустить его с помощью pytest команды:

$ pytest
================== test session starts =============================
platform darwin -- Python 3.7.3, pytest-5.3.0, py-1.8.0, pluggy-0.13.0
rootdir: /.../effective-python-testing-with-pytest
collected 2 items

test_with_pytest.py .F                                          [100%]

======================== FAILURES ==================================
___________________ test_always_fails ______________________________

    def test_always_fails():
>       assert False
E       assert False

test_with_pytest.py:5: AssertionError
============== 1 failed, 1 passed in 0.07s =========================

pytest представляет результаты теста иначе, чем unittest. Отчет показывает:

  1. Состояние системы, включая версии Python pytest и все установленные плагины.
  2. rootdir Или каталог для поиска под для настройки и испытаний
  3. Количество обнаруженных тестов

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

  • Точка ( .) означает, что тест пройден.
  • F означает, что тест не пройден.
  • E означает, что тест вызвал неожиданное исключение.

В случае неудачных испытаний в отчете приводится подробная разбивка ошибки. В приведенном выше примере тест не пройден, потому что assert False всегда делает сбой. Наконец, отчет содержит состояние набора тестов.

Вот несколько более быстрых примеров утверждений:

def test_uppercase():
    assert "loud noises".upper() == "LOUD NOISES"

def test_reversed():
    assert list(reversed([1, 2, 3, 4])) == [4, 3, 2, 1]

def test_some_primes():
    assert 37 in {
        num
        for num in range(1, 50)
        if num != 1 and not any([num % div == 0 for div in range(2, num)])
    }

Кривая обучения для этого pytest меньше, чем для, unittest потому что вам не нужно изучать новые конструкции для большинства тестов. Кроме того, использование assert, которое вы, возможно, использовали ранее в своем коде реализации, делает ваши тесты более понятными.

Управление состоянием и зависимостями

Ваши тесты часто будут зависеть от фрагментов данных или двойников теста для некоторых объектов в вашем коде. В unittest, вы можете извлечь эту зависимость в setUp() и tearDown() методах , так что каждый тест в классе может использовать их. Но при этом вы можете непреднамеренно сделать зависимость теста от конкретного фрагмента данных или объекта полностью неявной .

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

pytest принимает другой подход. Это приводит вас к явным объявлениям зависимостей, которые по-прежнему можно использовать повторно благодаря наличию фиксаторов . pytest фикстуры – это функции, которые создают данные или проверяют дубликаты, либо инициализируют некоторое состояние системы для набора тестов. Любой тест, который хочет использовать фикстуры, должен явно принять его в качестве аргумента, поэтому зависимости всегда указываются заранее.

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

Тестовая фильтрация

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

  • Фильтрация на основе имен: вы можете ограничить запуск только тех тестов, чьи полные имена соответствуют определенному выражению. Вы можете сделать это с помощью -k параметра.
  • Область видимости каталога: по умолчанию будут запускаться только те тесты, которые находятся в текущем каталоге или под ним.
  • Категоризация тестаpytest может включать или исключать тесты из определенных вами категорий. Вы можете сделать это с помощью -m параметра.

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

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

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

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

Архитектура на основе плагинов

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

Хотя некоторые pytest плагины ориентированы на конкретные платформы, такие как Django , другие применимы к большинству тестовых пакетов. 

Фикстуры: управление состоянием и зависимостями

pytest приспособления – это способ предоставления данных, дубликатов тестов или настройки состояния ваших тестов. Фикстуры – это функции, которые могут возвращать широкий диапазон значений. Каждый тест, который зависит от прибора, должен явно принять этот прибор в качестве аргумента.

Когда создавать фикстуры

Представьте, что вы пишете функцию format_data_for_display() для обработки данных, возвращаемых конечной точкой API. Данные представляют собой список людей, у каждого из которых есть имя, фамилия и должность. Функция должна вывести список строк, которые включают полное имя каждого человека (их given_name сопровождаются их family_name), двоеточие и их title. Чтобы проверить это, вы можете написать следующий код:

def format_data_for_display(people):
    ...  # Implement this!

def test_format_data_for_display():
    people = [
        {
            "given_name": "Alfonsa",
            "family_name": "Ruiz",
            "title": "Senior Software Engineer",
        },
        {
            "given_name": "Sayid",
            "family_name": "Khan",
            "title": "Project Manager",
        },
    ]

    assert format_data_for_display(people) == [
        "Alfonsa Ruiz: Senior Software Engineer",
        "Sayid Khan: Project Manager",
    ]

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

def format_data_for_excel(people):
    ... # Implement this!

def test_format_data_for_excel():
    people = [
        {
            "given_name": "Alfonsa",
            "family_name": "Ruiz",
            "title": "Senior Software Engineer",
        },
        {
            "given_name": "Sayid",
            "family_name": "Khan",
            "title": "Project Manager",
        },
    ]

    assert format_data_for_excel(people) == """given,family,title
Alfonsa,Ruiz,Senior Software Engineer
Sayid,Khan,Project Manager
"""

Если вы обнаружите, что пишете несколько тестов, в которых все используют одни и те же базовые тестовые данные, то это решение может быть в будущем. Вы можете вытащить повторяющиеся данные в одну функцию, помеченную символом, @pytest.fixture чтобы указать, что эта функция является pytest фикстурой:

import pytest

@pytest.fixture
def example_people_data():
    return [
        {
            "given_name": "Alfonsa",
            "family_name": "Ruiz",
            "title": "Senior Software Engineer",
        },
        {
            "given_name": "Sayid",
            "family_name": "Khan",
            "title": "Project Manager",
        },
    ]

Вы можете использовать фикстуру, добавив её в качестве аргумента в свои тесты. Её значением будет возвращаемое значение функции фикстуры:

def test_format_data_for_display(example_people_data):
    assert format_data_for_display(example_people_data) == [
        "Alfonsa Ruiz: Senior Software Engineer",
        "Sayid Khan: Project Manager",
    ]

def test_format_data_for_excel(example_people_data):
    assert format_data_for_excel(example_people_data) == """given,family,title
Alfonsa,Ruiz,Senior Software Engineer
Sayid,Khan,Project Manager
"""

Каждый тест теперь значительно короче, но все еще имеет четкий путь к данным, от которых зависит. Обязательно назовите свою фикстуру чем-то конкретным. Таким образом, вы можете быстро определить, хотите ли вы использовать его при написании новых тестов в будущем!

Когда следует избегать фикстуры

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

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

Фикстуры в масштабе

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

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

pytest ищет conftest.py модули по всей структуре каталогов. Каждый conftest.py предоставляет конфигурацию для дерева файлов, в котором он находится. Вы можете использовать любые фикстуры, которые определены в определенном conftest.py месте в родительском каталоге файла и в любых подкаталогах. Это отличное место для размещения ваших наиболее широко используемых фикстур.

Еще один интересный пример использования фикстур – защита доступа к ресурсам. Представьте, что вы написали набор тестов для кода, который имеет дело с вызовами API . Вы хотите убедиться, что набор тестов не выполняет никаких реальных сетевых вызовов, даже если тест случайно выполняет код реального сетевого вызова. pytest предоставляет monkeypatch приспособление для замены значений и поведения, которое вы можете использовать для достижения максимального эффекта:

# conftest.py

import pytest
import requests

@pytest.fixture(autouse=True)
def disable_network_calls(monkeypatch):
    def stunted_get():
        raise RuntimeError("Network access not allowed during testing!")
    monkeypatch.setattr(requests, "get", lambda *args, **kwargs: stunted_get())

Размещая disable_network_calls() в conftest.py и добавление autouse=True опции, вы убедитесь , что сетевые вызовы будут отключены в каждом комплекте. Любой тест, который выполняет вызов кода requests.get(), вызовет RuntimeError указание на то, что произошел неожиданный сетевой вызов.

Метки: классификация тестов

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

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

Маркировка тестов полезна для классификации тестов по подсистемам или зависимостям. Если для некоторых ваших тестов требуется, например, доступ к базе данных, вы можете создать @pytest.mark.database_access отметку для них.

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

--strict-markers флаг в pytestкоманде гарантирует , что все знаки в ваших тестах регистрируются в вашей pytest конфигурации. Это предотвратит запуск ваших тестов до тех пор, пока вы не зарегистрируете неизвестные отметки.

Для получения дополнительной информации о регистрации знаков ознакомьтесь с pytest документацией .

Когда приходит время для запуска ваших тестов, вы все равно можете запустить их все по умолчанию с помощью pytest команды. Если вы хотите запускать только те тесты, которые требуют доступа к базе данных, то вы можете использовать pytest -m database_access. Для запуска всех тестов, кроме тех, которые требуют доступа к базе данных, вы можете использовать pytest -m "not database_access". Вы даже можете использовать autouse прибор для ограничения доступа к базе данных теми тестами, которые отмечены значком database_access.

Некоторые плагины расширяют функциональность меток, защищая доступ к ресурсам. pytest-django плагин дает django_db знак. Любые тесты без этой отметки, которые пытаются получить доступ к базе данных, потерпят неудачу. Первый тест, который пытается получить доступ к базе данных, инициирует создание тестовой базы данных Django.

Требование о добавлении django_db метки подталкивает вас к явному указанию ваших зависимостей. Это pytest философия, в конце концов! Это также означает, что вы можете запускать тесты, которые не основываются на базе данных намного быстрее, потому что pytest -m "not django_db" не позволят тесту инициировать создание базы данных. Экономия времени действительно возрастает, особенно если вы стараетесь часто проводить тесты.

pytest предоставляет несколько отметок из коробки:

  • skip пропускает тест безоговорочно.
  • skipif пропускает тест, если переданное ему выражение оценивается как True.
  • xfail указывает на то, что тест, как ожидается, не пройден, поэтому, если тест не пройден, общий набор может все же привести к прохождению статуса.
  • parametrize (обратите внимание на написание) создает несколько вариантов теста с различными значениями в качестве аргументов. Вы узнаете больше об этой отметке в ближайшее время.

Вы можете увидеть список всех марок, запустив pytest --markers.

Параметризация: комбинированные тесты

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

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

def test_is_palindrome_empty_string():
    assert is_palindrome("")

def test_is_palindrome_single_character():
    assert is_palindrome("a")

def test_is_palindrome_mixed_casing():
    assert is_palindrome("Bob")

def test_is_palindrome_with_spaces():
    assert is_palindrome("Never odd or even")

def test_is_palindrome_with_punctuation():
    assert is_palindrome("Do geese see God?")

def test_is_palindrome_not_palindrome():
    assert not is_palindrome("abc")

def test_is_palindrome_not_quite():
    assert not is_palindrome("abab")

Все эти тесты, кроме двух последних, имеют одинаковую форму:

def test_is_palindrome_<in some situation>():
    assert is_palindrome("<some string>")

Вы можете использовать, @pytest.mark.parametrize() чтобы заполнить эту форму различными значениями, значительно уменьшая ваш тестовый код:

@pytest.mark.parametrize("palindrome", [
    "",
    "a",
    "Bob",
    "Never odd or even",
    "Do geese see God?",
])
def test_is_palindrome(palindrome):
    assert is_palindrome(palindrome)

@pytest.mark.parametrize("non_palindrome", [
    "abc",
    "abab",
])
def test_is_palindrome_not_palindrome(non_palindrome):
    assert not is_palindrome(non_palindrome)

Первый аргумент parametrize()– это разделенная запятыми строка имен параметров. Второй аргумент представляет собой список либо из кортежей или отдельных значений , которые представляют значение параметра (ов). Вы можете продвинуть свою параметризацию на шаг вперед, чтобы объединить все ваши тесты в один:

@pytest.mark.parametrize("maybe_palindrome, expected_result", [
    ("", True),
    ("a", True),
    ("Bob", True),
    ("Never odd or even", True),
    ("Do geese see God?", True),
    ("abc", False),
    ("abab", False),
])
def test_is_palindrome(maybe_palindrome, expected_result):
    assert is_palindrome(maybe_palindrome) == expected_result

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

Отчеты о продолжительности: боевые медленные тесты

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

Вы читали ранее об использовании меток для фильтрации медленных тестов при запуске вашего пакета. Если вы хотите повысить скорость своих тестов, полезно знать, какие тесты могут предложить самые большие улучшения. pytest может автоматически записывать продолжительность теста для вас и сообщать об основных нарушителях.

Используйте --durations опцию для pytest команды, чтобы включить отчет о продолжительности в результаты вашего теста. --durations ожидает целочисленное значение n и сообщит о самом медленном n количестве тестов. Результат будет соответствовать результатам вашего теста:

$ pytest --durations=3
3.03s call     test_code.py::test_request_read_timeout
1.07s call     test_code.py::test_request_connection_timeout
0.57s call     test_code.py::test_database_read
======================== 7 passed in 10.06s ==============================

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

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

Полезные pytest плагины

Вы узнали о нескольких ценных pytest плагинах ранее в этом уроке. Вы можете изучить эти и некоторые другие более подробно ниже.

pytest-randomly

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

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

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

pytest-cov

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

pytest-django

pytest-django предоставляет несколько полезных приспособлений и отметок для работы с Django. Вы видели django_db метку ранее в этом уроке, и rf прибор обеспечивает прямой доступ к экземпляру Django RequestFactory. Прибор settings обеспечивает быстрый способ установки или отмены настроек Django. Это большое повышение производительности тестирования Django!

pytest-bdd

pytest может использоваться для запуска тестов, которые выходят за рамки традиционной области модульного тестирования. Разработка на основе поведения (BDD) поощряет написание на понятном языке описания вероятных действий и ожиданий пользователя, которые затем можно использовать для определения необходимости реализации данной функции. pytest-bdd помогает вам использовать Gherkin для написания функциональных тестов для вашего кода.

Вы можете увидеть, какие другие плагины доступны pytest с этим обширным списком сторонних плагинов .

Вывод

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

В этом уроке вы узнали, как использовать:

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

Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram