Как сделать тест на питоне

Обновлено: 07.07.2024

Тестирование можно запустить из командной строки интерпретатора Python , используя команду:

В отличие от запуска напрямую командой pytest [. ] , запуск через Python добавит текущий каталог в sys.path .

Статусы завершения¶

Выполнение pytest может генерировать один из следующих статусов завершения:

Все тесты были собраны и успешно прошли

Тесты были собраны и запущены, но некоторые из них упали

Выполнение тестов было прервано пользователем

Во время выполнения тестов произошла внутренняя ошибка

Ошибка запуска pytest из командной строки

Не удалось собрать тесты (тесты не найдены)

Коллекция статусов представлена перечислением _pytest.config.ExitCode. Статусы завершения являются частью публичного API, их можно импортировать и использовать непосредственно:

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

Получение помощи по версии, параметрам, переменным окружения¶

Остановка после первых N падений¶

Чтобы остановить процесс тестирования после первых N падений, используются параметры:

Выбор выполняемых тестов¶

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

Запуск тестов модуля

Запуск тестов из директории

Запуск тестов, удовлетворяющих ключевому выражению

Эта команда запустит тесты, имена которых удовлетворяют заданному строковому выражению (без учета регистра). Строковые выражения могут включать операторы Python , которые используют имена файлов, классов и функций в качестве переменных. В приведенном выше примере будет запущен тест MyClass.test_something , но не будет запущен тест TestMyClass.test_method_simple .

Запуск тестов по идентификаторам узлов

Каждому собранному тесту присваивается уникальный идентификатор nodeid , который состоит из имени файла модуля, за которым следуют спецификаторы, такие как имена классов, имена функций и параметры из параметризации, разделенные символами :: :

Чтобы запустить конкретный тест из модуля, выполните:

Еще один пример спецификации тестового метода в командной строке:

Запуск маркированных тестов

Будут запущены тесты, помеченные декоратором @pytest.mark.slow .

Запуск тестов из пакетов

Будет импортирован пакет pkg.testing , и его расположение в файловой системе будет использовано для поиска и запуска тестов.

Детализация сводного отчета¶

По умолчанию для списка сбоев и ошибок используется добавочная комбинация fE .

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

  • f - упавшие (добавляет раздел FAILED)

  • E - ошибки (добавляет раздел ERROR)

  • s - пропущенные (добавляет раздел SKIPPED)

  • x - тесты XFAIL (добавляет раздел XFAIL)

  • X - тесты XPASS (добавляет раздел XPASS)

  • p - успешные (passed)

  • P - успешные (passed) с выводом

Есть и специальные символы для пропуска отдельных групп:

  • a - выводить все, кроме pP

  • A - выводить все

  • N - ничего не выводить (может быть полезным, поскольку по умолчанию используется комбинация fE ).

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

Использование p добавляет в сводный отчет успешные тесты, а P добавляет дополнительный раздел «пройдены” (PASSED) для тестов, которые прошли, но перехватили вывод:

Запуск отладчика PDB (Python Debugger) при падении тестов¶

python содержит встроенный отладчик PDB (Python Debugger). pytest позволяет запустить отладчик с помощью параметра командной строки:

Использование параметра позволяет запускать отладчик при каждом падении теста (или прерывании его с клавиатуры). Часто хочется сделать это для первого же упавшего теста, чтобы понять причину его падения:

Обратите внимание, что при любом падении информация об исключении сохраняется в sys.last_value , sys.last_type и sys.last_traceback . При интерактивном использовании это позволяет перейти к отладке после падения с помощью любого инструмента отладки. Можно также вручную получить доступ к информации об исключениях, например:

Запуск отладчика PDB (Python Debugger) в начале теста¶

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

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

Установка точек останова¶

Чтобы установить точку останова, вызовите в коде import pdb;pdb.set_trace() , и pytest автоматически отключит перехват вывода для этого теста, при этом:

на перехват вывода в других тестах это не повлияет;

весь перехваченный ранее вывод будет обработан как есть;

перехват вывода возобновится после завершения отладочной сессии (с помощью команды continue ).

Использование встроенной функции breakpoint¶

Python 3.7 содержит встроенную функцию breakpoint() . pytest поддерживает использование breakpoint() следующим образом:

  • если вызывается breakpoint() , и при этом переменная PYTHONBREAKPOINT установлена в значение по умолчанию, pytest использует расширяемый отладчик PDB вместо системного;

  • когда тестирование будет завершено, система снова будет использовать отладчик Pdb по умолчанию;

  • если pytest вызывается с опцией --pdb то расширяемый отладчик PDB используется как для функции breakpoint() , так и для упавших тестов/необработанных исключений;

  • для определения пользовательского класса отладчика можно использовать --pdbcls .

Профилирование продолжительности выполнения теста¶

Чтобы получить список 10 самых медленных тестов, выполните:

По умолчанию, pytest не покажет тесты со слишком маленькой (менее одной сотой секунды) длительностью выполнения, если в командной строке не будет передан параметр -vv .

Модуль faulthandler ¶

Стандартный модуль faulthandler можно использовать для сброса трассировок Python при ошибке или по истечении времени ожидания.

При запуске pytest модуль автоматически подключается, если только в командной строке не используется опция -p no:faulthandler .

Кроме того, для сброса трассировок всех потоков в случае, когда тест длится более X секунд, можно использовать опцию faulthandler_timeout=X (для Windows неприменима).

Эта функциональность была интегрирована из внешнего плагина pytest-faulthandler с двумя небольшими изменениями:

чтобы ее отключить, используйте -p no:faulthandler вместо --no-faulthandler ;

опция командной строки --faulthandler-timeout превратилась в конфигурационную опцию faulthandler_timeout. Ее по-прежнему можно настроить из команндной строки, используя -o faulthandler_timeout=X .

Создание файлов формата JUnit¶

Чтобы создать результирующие файлы в формате, понятном Jenkins или другому серверу непрерывной интеграции, используйте вызов:

Команда создает xml-файл по указанному пути.

Чтобы задать имя корневого xml-элемента для набора тестов, можно настроить параметр junit_suite_name в конфигурационном файле:

Спецификация JUnit XML, по-видимому, указывает, что атрибут "time" должен сообщать об общем времени выполнения теста, включая выполнение setup- и teardown- методов (1, 2). Это поведение pytest по умолчанию. Чтобы вместо этого сообщать только о длительности вызовов, настройте параметр junit_duration_report следующим образом:

record_property¶

Чтобы записать дополнительную информацию для теста, используйте фикстуру record_property :

Такая запись добавит дополнительное свойство example_key="1" к сгенерированному тегу testcase :

Эту функциональность также можно использовать совместно с пользовательскими маркерами:

В файле получим:

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

record_xml_attribute¶

Чтобы добавить дополнительный атрибут в элемент testcase , можно использовать фикстуру record_xml_attribute . Ее также можно использовать для переопределения существующих значений:

В отличие от record_property , дочерний элемент в данном случае не добавляется. Вместо этого в элемент testcase будет добавлен атрибут assertions="REQ-1234" , а значение атрибута classname по умолчанию будет заменено на "classname=custom_classname" :

record_xml_attribute пока используется в режиме эксперимента, и в будущем может быть заменен чем-то более мощным и/или общим. Однако сама функциональность как таковая будет сохранена.

Использование record_xml_attribute поверх record_xml_property может быть полезным при парсинге xml-отчетов средствами непрерывной интеграции. Однако некоторые парсеры допускают не любые элементы и атрибуты. Многие инструменты (как в примере ниже), используют xsd-схему для валидации входящих xml. Поэтому убедитесь, что имена атрибутов, которые вы используете, являются допустимыми для вашего парсера.

Ниже представлена схема, которую использует Jenkins для валидации xml-отчетов:

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

Чтобы добавить свойства каждому тесту из набора, можно использовать фикстуру record_testsuite_property с параметром scope="session" (в этом случае она будет применяться ко всем тестам тестовой сессии).

Этой фикстуре передаются имя ( name ) и значение ( value ) тэга

, который добавляется на уровне тестового набора для генерируемого xml-файла:

name должно быть строкой, а value будет преобразовано в строку и корректно экранировано.

В отличие от случаев использования record_property и record_xml_attribute созданный xml-файл будет совместим с последним стандартом xunit .

Создание файлов в формате resultlog¶

Для создания машиночитаемых логов в формате plain-text можно выполнить

и просмотреть содержимое по указанному пути path . Эти файлы также используются ресурсом PyPy-test для отображения результатов тестов после ревизий.

Поскольку эта возможность редко используется, она запланирована к удалению в pytest 6.0 .

Если вы пользуетесь ею, рассмотрите возможность использования нового плагина pytest-reportlog .

Отправка отчетов на сервис pastebin¶

Создание ссылки для каждого упавшего теста:

Создание ссылки для лога тестовой сессии:

Изменено в вресии 5.2

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

Подключение плагинов¶

В командной строке можно явно подгрузить какой-либо внутренний или внешний плагин, используя опцию -p :

Опция принимает параметр name , который может быть:

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

Отключение плагинов¶

Чтобы отключить загрузку определенных плагинов во время вызова, используйте опцию -p с префиксом no: .

Вызов pytest из кода Python¶

pytest можно вызвать прямо в коде Python:

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

Пример выполнения

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

Вот модульный тест для метода stop() чтобы подогреть аппетит. Я буду вдаваться в подробности позже.

Руководство по модульному тестированию

совершить

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

Быть дисциплинированным

Автоматизировать

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

Непроверенный код разбит по определению

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

Что такое юнит?

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

В TDD или не в TDD

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

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

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

Модуль Unittest

Модуль unittest поставляется со стандартной библиотекой Python. Он предоставляет класс TestCase , из которого вы можете получить свой класс. Затем вы можете переопределить метод setUp() чтобы подготовить тестовое устройство перед каждым тестом, и / или метод класса classSetUp() чтобы подготовить тестовое устройство для всех тестов (не сбрасывать между отдельными тестами). Существуют также соответствующие tearDown() и classTearDown() которые вы можете переопределить.

Вот соответствующие части из нашего класса SelfDrivingCarTest . Я использую только метод setUp() . Я создаю свежий экземпляр SelfDrivingCar и сохраняю его в self.car чтобы он был доступен для каждого теста.

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

  • Подготовьте среду (по желанию).
  • Подготовьте ожидаемый результат.
  • Назовите тестируемый код.
  • Утверждают, что фактический результат соответствует ожидаемому результату.

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

Например, метод stop() класса SelfDrivingCar ничего не возвращает, но он изменяет внутреннее состояние, устанавливая скорость равной 0. Метод assertEqual() предоставляемый базовым классом TestCase , используется здесь для проверки того, что вызов stop() работал как ожидалось.

Здесь на самом деле два теста. Первый тест — убедиться, что если скорость автомобиля равна 5 и вызывается stop() , то скорость становится равной 0. Затем еще один тест — убедиться, что ничего не происходит, если снова вызвать stop() когда автомобиль уже остановлен.

Позже я представлю еще несколько тестов для дополнительной функциональности.

Модуль Doctest

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

Я не использую и не рекомендую doctest для крупных систем. Правильное юнит-тестирование требует много работы. Тестовый код обычно намного больше, чем тестируемый код. Строки документации просто не подходят для написания всесторонних тестов. Они крутые, хотя. Вот как выглядит factorial функция с doc-тестами:

while factor Как видите, строка документации намного больше, чем код функции. Это не способствует удобочитаемости.

Запуск тестов

OK. Вы написали свои юнит-тесты. Для большой системы у вас будет десятки / сотни / тысячи модулей и классов в нескольких каталогах. Как вы выполняете все эти тесты?

Модуль unittest предоставляет различные средства для группировки тестов и их программного запуска. Проверьте загрузку и запуск тестов . Но самый простой способ — это тестовое открытие. Эта опция была добавлена ​​только в Python 2.7. До 2.7 вы могли использовать нос, чтобы обнаружить и запустить тесты. У Nose есть несколько других преимуществ, таких как запуск тестовых функций без необходимости создавать класс для ваших тестовых случаев. Но для целей этой статьи давайте придерживаться unittest.

Чтобы обнаружить и запустить свои тесты, основанные на unittest, просто введите в командной строке:

python -m unittest discover

Есть несколько флагов, которые управляют операцией:

Тестовое покрытие

Тестовое покрытие — это поле, которым часто пренебрегают. Охват означает, сколько кода на самом деле проверено вашими тестами. Например, если у вас есть функция с оператором if-else и вы тестируете только ветку if , тогда вы не знаете, работает ли ветвь else или нет. В следующем примере кода функция add() проверяет тип своих аргументов. Если оба являются целыми числами, он просто добавляет их.

Практические юнит-тесты

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

Дизайн для тестируемости

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

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

Например, наш класс SelfDrivingCar отвечает за работу машины на высоком уровне: идти, останавливаться, перемещаться. У него есть метод calculate_distance_to_object_in_front() который еще не был реализован. Эта функциональность, вероятно, должна быть реализована совершенно отдельной подсистемой. Он может включать в себя считывание данных с различных датчиков, взаимодействие с другими автомобилями с автоматическим управлением, целый стек машинного зрения для анализа изображений с нескольких камер.

Посмотрим, как это работает на практике. SelfDrivingCar примет аргумент с именем object_detector , у которого есть метод object_detector calculate_distance_to_object_in_front() , и делегирует эту функциональность этому объекту. Теперь нет необходимости в модульном тестировании, потому что object_detector отвечает (и должен быть проверен) за это. Вы все еще хотите провести модульное тестирование того факта, что вы правильно используете object_detector .

Затрат и выгод

Например, наш класс для самостоятельного вождения очень важен. Если метод stop() не работает должным образом, наша машина с автоматическим управлением может убить людей, уничтожить имущество и сорвать весь рынок автомобилей с автоматическим управлением. Если вы разрабатываете автомобиль с автоматическим управлением, я подозреваю, что ваши юнит-тесты для метода stop() будут немного более строгими, чем мой.

Тестирование мышления

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

Например, предположим, что ваш код должен что-то вычислять. Для этого ему необходимо загрузить некоторые данные из базы данных, прочитать файл конфигурации и динамически обращаться к API REST для получения актуальной информации. Все это может потребоваться по разным причинам, но объединение всего этого в одну функцию значительно усложнит модульное тестирование. Это все еще возможно с помощью макетов, но гораздо лучше правильно структурировать ваш код.

Чистые функции

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

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

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

Почему? Потому что код не изменился. Он по-прежнему ожидает файл конфигурации XML, а ваш тест все еще создает для него файл XML. Но в производстве ваш код получит файл JSON, который он не сможет проанализировать.

Тестирование обработки ошибок

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

Как правило, вы хотите проверить ввод в открытом интерфейсе вашего кода, потому что вы не обязательно знаете, кто будет вызывать ваш код. Давайте посмотрим на метод drive() самостоятельного вождения автомобиля. Этот метод ожидает параметр ‘destination’. Параметр ‘destination’ будет использоваться позже в навигации, но метод привода ничего не делает для проверки его правильности.

Давайте предположим, что пункт назначения должен быть кортежем широты и долготы. Существуют всевозможные тесты, которые можно проверить, чтобы убедиться, что он действителен (например, пункт назначения посреди моря). Для наших целей давайте просто убедитесь, что это кортеж с плавающей точкой в ​​диапазоне от 0,0 до 90,0 для широты и от -180,0 до 180,0 для долготы.

Вот обновленный класс SelfDrivingCar . Я реализовал тривиально некоторые из не реализованных методов, потому что метод drive() вызывает некоторые из этих методов прямо или косвенно.

В этой статье мы рассмотрим модуль Python unittest и некоторые из его распространенных вариантов использования.

Но перед этим давайте разберемся, зачем нам вообще нужен этот модуль.

Почему следует использовать модуль unittest?

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

Этап 1 — это этап разработки, на котором вы воплощаете свою основную идею в простое приложение.

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

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

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

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

Виды тестирования

Для приложения существует два типа тестов:

Интегрированные тесты — это тесты, которые проверяют, правильно ли работают модули приложения друг с другом.

Модульные тесты — это тесты, которые проверяют небольшие компоненты в приложении.

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

Модуль Python unittest на примере

Этот модуль встроен в вашу установку Python 3+, поэтому нет необходимости устанавливать его с помощью pip.

Вы можете импортировать модуль, набрав:

Методы

В этом модуле есть несколько методов, с помощью которых вы можете выполнять модульные тесты.

Наиболее распространенные из них перечислены в таблице ниже.

Метод Проверка утверждения
assertEqual (a, b) а == б
assertNotEqual (a, b) а! = Ь
assertTrue (x) bool (x) истинно
assertFalse (x) bool (x) ложно
assertIs (а, б) а это б
assertIsNot (а, б) а не б
assertIsNone (x) x нет
assertIsNotNone (x) x не None
assertIn (а, б) а в б
assertNotIn (а, б) а не в б
assertIsInstance (а, б) isinstance (а, б)
assertNotIsInstance (a, b) не isinstance (а, б)

Написание модульного теста

Нам нужна программа для проведения тестов. Итак, напишем ее.

Я напишу программу, которая просто пытается проверить сумму элементов в списке.

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

Я назову свой класс MyTestClass .

Чтобы написать тестовый метод, мы должны добавить к имени метода префикс test_ . Итак, любой метод тестирования должен иметь вид test_xyz()

Я пишу метод test_list() который проверяет, равна ли сумма элементов в списке 15, и аналогично другой метод проверки данной строки.

Я использую метод unittest assertEqual() , который запускает unittest и проверяет, выполняется ли это утверждение.

Теперь давайте выполним этот файл с помощью Python.

Как видите, первый тест прошел, а второй — нет, так как строки не совпадают.

Запуск модульных тестов в приложении

Теперь давайте запустим модульные тесты в другой программе, поскольку вы не будете писать все свое приложение внутри файла unittest!

Напишем простую прикладную программу и проведем на ней модульные тесты.

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

Сохраните приведенный ниже файл как test_example.py как мы будем ссылаться на него в следующем фрагменте кода.

Рекомендуемый метод

Обычно модули тестирования хранятся отдельно от основного приложения.

Таким образом, мы будем импортировать модуль unittest только на этапе тестирования.

Python позволяет нам это сделать, указав параметр -m MODULE_NAME . Итак, наша команда будет:

Теперь вам не нужно писать import unittest в вашем приложении!

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

Теперь, когда мы написали тесты отдельно, давайте проверим, работает ли он.

Unittest пример

Это действительно работает, поскольку оба наших теста прошли успешно!

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

Pytest - тестирование приложений в Python 3

Статьи

Обзор мощной библиотеки для тестирования кода Pytest.

Введение

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

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

Python действительно предоставляет встроенные инструменты, такие как unittest, для поддержки тестирования, но он включает в себя написание большого количества шаблонного кода. Он также имеет ограниченную возможность повторного использования компонентов (или приспособлений в PyTest). Поэтому я буду тестировать приложения Python с помощью Pytest вместо других инструментов. Pytest также является самым популярным инструментом среди других альтернатив.

Примечание: В этой статье я буду использовать Python 3.

Почему Pytest?

Pytest — одна из самых популярных библиотек, посвященных модульному и функциональному тестированию. Но что делает её такой популярной? Вот ответ:

  • Меньше шаблонности.
  • Установочный код можно использовать повторно с помощью приспособлений.
  • Фильтрация тестов во время выполнения (для одновременного выполнения только определенного набора тестов).
  • Параметризация тестов (предоставление различных входных значений одному и тому же тесту, позволяющее тестировать различные сценарии с использованием одного теста).
  • Архитектура на основе плагинов, обеспечивающая гибкость и более широкое внедрение.
  • Возможность параллельно выполнять тесты.

Установка Pytest

Pytest — это библиотека, которую нам нужно будет добавить в наш проект. Как известно, я всегда выбираю для программирования виртуальную среду и работаю исключительно в ней:

А потом я устанавливаю Pytest:

Это позволит включить команду pytest в нашей установочной среде. Установка завершает наш первый шаг в тестировании приложений Python с помощью Pytest. Давайте перейдем к следующему шагу.

Соглашения об именовании

Как и в любом тестовом фреймворке, в Pytest есть несколько мест, где он автоматически ищет тестовые файлы.

А чтобы выполнить все тесты в нашем каталоге pytest-demo, я запускаю:

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

Или, если я хочу игнорировать каталог (например, виртуальную среду), то я могу использовать:

Настройка кода

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

Тестирование приложений

Теперь, когда у нас есть наш минимальный фрагмент кода, мы можем начать с нашего основного теста. Мы будем делать расчет 2 + 1 = 3. Для этого я определю наш тест как:

Ключевое слово assert сравнивает два значения, которые оно получает, и возвращает True или False на основе их равенства. Мы также можем иметь подробные утверждения, которые могут быть полезны при отладке. Они могут быть записаны как:

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

Наконец, мы можем запустить наш тест с помощью команды:

И вот, у нас есть наш первый успешный тест!

Обзор мощной библиотеки для тестирования кода Pytest.

Точно так же мы можем написать тест и для нашего метода вычитания:

Уровень отладки Pytest

Я могу передать параметр во время выполнения тестов, чтобы увеличить/уменьшить многословность выходных данных, генерируемых Pytest. Доступны следующие варианты:

  • v: увеличивает многословность.
  • q: более тихий вывод.
  • r: сводка тестов.
  • rp: сводка пройденных тестов.
  • rp: сводка неудачных тестов.

Заключение

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

Читайте также: