PyTest

Содержание
Introduction
Example
Структура проекта
Тестирование проверки аргументов на тип
Запуск unittest тестов
Добавить PyTest в PyCharm
Похожие статьи

Введение

Pytest поддерживает тесты, созданные с unittest .

Главное преимущество Pytest заключается в особенностях написания TestCase.

TestCase в pytest — это серия функций в файле Python, которые начинаются с имени test_.

У Pytest есть и другие отличительные особенности:

Написание теста TestSum в pytest выглядит так:

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"

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

Пример без IDE

Простейший пример в консоле Linux

Нужно подготовить окружение и создать два файла - с кодом и тестом для этого кода.

Файл с кодом можно назвать как угодно - желательно с маленькой буквы и именем несовпадающим с зарезервированными.

Файл с тестом обычно называют также но с префиксом test_ или реже постфиксом _test

mkdir /home/$(whoami)/python/pytest/qa
cd /home/$(whoami)/python/pytest/qa
python -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
python -m pip install pytest
touch psum.py test_psum.py

В файле psum.py напишите простую функцию, например сложение

def add(x, y): return x + y

А в файле test_psum.py будет тест для этой функции

from psum import add def test_psum(): assert add(2, 3) == 5, "Should be 5"

Чтобы запустить тест нужно выполнить

pytest test_psum.py

================================================= test session starts ================================================== platform linux -- Python 3.9.5, pytest-7.0.1, pluggy-1.0.0 rootdir: /home/andrei/python/pytest/qa collected 1 item test_psum . py . [100%] ================================================== 1 passed in 0.01s ===================================================

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

assert add(2, 3) == 999, "Should be 999"

pytest test_psum.py

================================================= test session starts ================================================== platform linux -- Python 3.9.5, pytest-7.0.1, pluggy-1.0.0 rootdir: /home/andrei/python/pytest/qa collected 1 item test_psum.py F [100%] ======================================================= FAILURES ======================================================= ______________________________________________________ test_psum _______________________________________________________ def test_psum(): > assert add(2, 3) == 999, "Should be 999" E AssertionError: Should be 999 E assert 5 == 999 E + where 5 = add(2, 3) test_psum.py:4: AssertionError =============================================== short test summary info ================================================ FAILED test_psum.py::test_psum - AssertionError: Should be 999 ================================================== 1 failed in 0.02s ===================================================

Структура проекта с тестами на PyTest

Как только проект перерастает микроскопический размер держать тесты в одной директории с кодом становится неудобно

Предположим, что код проекта лежит в директории app можно переложить файл с тестом test_psum.py в поддиректорию tests

app ├── psum.py ├── __pycache__ │ ├── psum.cpython-39.pyc │ └── test_psum.cpython-39-pytest-7.0.1.pyc ├── tests │ ├── __pycache__ │ └── test_psum.py └── venv ├── bin ├── include ├── lib ├── lib64 -> lib └── pyvenv.cfg

Если теперь запустить тест из директории app то pytest поймёт как импортировать psum

python -m pytest tests/test_psum.py

Если запустить этот же тест прямо из директории tests - появится ошибка ImportError while importing test module

Тестирование проверки аргументов на тип

Демонстрацю применения PyTest часто начинают с функций сложения или умножения.

Например

# Code def prod(a, b): return a * b

# Test from prod import prod def test_prod(): res = prod(3, 4) assert res == 12

python -m pytest tests/test_prod.py

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

С помощью добавим валидацию и напишем тест.

# prod.py def prod(a, b): if not all( map(lambda p: isinstance(p, (int, float)), (a, b)) ): raise TypeError("Not valid argument data type") print("prod.py: Valid arguments") return a * b

# test_prod.py import pytest from prod import prod def test_prod(): res = prod(3, 4) assert res == 12 def test_arguments(): try: # Заведомо неправильный тип данных должен быть пойман # "" is a string and should not be accepted res = prod("", 4) except TypeError as err: # if TypeError is caught pass else: print("test_prod.py: Invalid argument is not caught") pytest.fail() # assert False

Вместо pytest.fail() можно использовать assert False, тогде и импортировать pytest необязательно

python -m pytest -v tests/test_prod.py

================================ test session starts ================================ platform linux -- Python 3.9.5, pytest-7.0.1, pluggy-1.0.0 -- /home/andrei/python/pytest/otus/venv/bin/python cachedir: .pytest_cache rootdir: /home/andrei/python/pytest/app collected 2 items tests/test_prod.py::test_prod PASSED [ 50%] tests/test_prod.py::test_arguments PASSED [100%] ================================= 2 passed in 0.01s =================================

Если тест сломается PyTest выдаст следующий результат

================================ test session starts ================================ platform linux -- Python 3.9.5, pytest-7.0.1, pluggy-1.0.0 -- /home/andrei/python/pytest/otus/venv/bin/python cachedir: .pytest_cache rootdir: /home/andrei/python/pytest/app collected 2 items tests/test_prod.py::test_prod PASSED [ 50%] tests/test_prod.py::test_arguments FAILED [100%] ===================================== FAILURES ====================================== __________________________________ test_arguments ___________________________________ def test_arguments(): try: # "" is a string and should not be accepted res = prod(3, 4) except TypeError as err: # if TypeError is caught pass else: print("test_prod.py: Invalid argument is not caught") > pytest.fail() E Failed tests/test_prod.py:19: Failed ------------------------------- Captured stdout call -------------------------------- prod.py: Valid arguments test_prod.py: Invalid argument is not caught ============================== short test summary info ============================== FAILED tests/test_prod.py::test_arguments - Failed ============================ 1 failed, 1 passed in 0.02s ============================

Изображение баннера

unittest из PyTest

Если на проекте уже есть тесты, созданные на unittest можно их не переписывать - PyTest поймёт синтаксис unittest

Рассмотрим проверку решения квадратного уравнения на unittest

Если запустить эти же тесты с помощью PyTest

python -m pytest -v tests/test_quadratic.py

================================================== test session starts =================================================== platform linux -- Python 3.9.5, pytest-7.0.1, pluggy-1.0.0 -- /home/andrei/python/unittest/app/venv/bin/python cachedir: .pytest_cache rootdir: /home/andrei/python/unittest/app collected 5 items tests/test_quadratic . py::TestQuadratic::test_raises_type_error PASSED [ 20%] tests/test_quadratic . py::TestQuadratic::test_result_is_tuple PASSED [ 40%] tests/test_quadratic . py::TestQuadratic::test_single_root PASSED [ 60%] tests/test_quadratic . py::TestQuadratic::test_two_roots PASSED [ 80%] tests/test_quadratic . py::TestQuadratic::test_zero_a_and_b PASSED [100%] =================================================== 5 passed in 0.01s ====================================================

Добавить PyTest в Pycharm

Чтобы добавить PyTest в PyCharm воспользуйтесь следующей инструкцией

Settings (Ctrl + Alt + S) → Tools → Python Integrated Tools → Default test runner:

Выбрать pytest. Если он ещё не был добавлен появится предупреждение и кнопка Fix.

Добавить PyTest в PyCharm изображение с сайта www.aredel.com
PyTest не найден

Нужно нажать кнопку Fix

Внизу главного экрана настроек появится сообщение

Installing package 'pytest'

Дождитесь когда оно сменится сообщением об успешной установке и с экрана исчезнет предупреждение.

Добавить PyTest в PyCharm изображение с сайта www.aredel.com
PyTest как default test runner

Article author: Andrei Olegovich

Похожие статьи
Тестирование
Python

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: