Систематическое тестирование программного обеспечения, особенно в сообществе Python, часто либо полностью игнорируются или выполняются специальным образом. Многие программисты на Python совершенно не подозревают о существовании pytest. Брайен Оккен берет на себя труд, доказать, что тестирование программного обеспечения с помощью pytest легко, естественно и даже интересно.
Dmitry Zinoviev
Author of Data Science Essentials in Python
Примеры в этой книге написаны с использованием Python 3.6 и pytest 3.2. pytest 3.2 поддерживает Python 2.6, 2.7 и Python 3.3+.
Исходный код для проекта Tasks, а также для всех тестов, показанных в этой книге, доступен по ссылке на веб-странице книги в pragprog.com. Вам не нужно загружать исходный код, чтобы понять тестовый код; тестовый код представлен в удобной форме в примерах. Но что бы следовать вместе с задачами проекта, или адаптировать примеры тестирования для проверки своего собственного проекта (руки у вас развязаны!), вы должны перейти на веб-страницу книги и скачать работу. Там же, на веб-странице книги есть ссылка для сообщений errata и дискуссионный форум.
Под спойлером приведен список статей этой серии.
Благодарности
Сначала я должен поблагодарить Мишель — мою жену и лучшего друга. Жаль, что вы не видите комнату, в которой я пишу. Вместо стола у меня антикварный квадратный дубовый обеденный стол на котором достаточно места, где можно разложить бумаги. Красивый стеклянный книжный шкаф с моими ретро — космическими игрушками, которые мы собрали за долгие годы, а также техническими книгами, монтажными платами и жонглерскими шарами. Старинные алюминиевые ящики для хранения бумаги доверху заполненные заметками, шнурами и даже оставшимися наклейками для ракет. Одна стена покрыта бархатом, который мы купили много лет назад, когда магазин тканей решил закрыться насовсем. Ткань должна успокоить эхо, когда я записываю подкасты.
Мне нравится писать здесь не только потому, что это удобно и соответствует моему внутреннему миру, но и потому, что это пространство, которое Мишель создала со мной и для меня. Мы с ней всегда были командой, и она невероятно поддерживала мои сумасшедшие идеи написать блог, начать подкаст или два, и теперь, в течение последнего года или около того, написать эту книгу. Она позаботилась о том, чтобы у меня было время и пространство для письма. Когда я устаю и задумываюсь о том, что есть-ли у меня ещё силы, чтобы писать, она предлагает мне просто продолжить в течение двадцати минут и понаблюдать, как я буду себя тогда чувствовать, так же она делала, когда помогла мне пройти через поздние ночи учебы в колледже. Я правда, правда не смог бы сделать это без нее.
У меня также есть две удивительно удивительные, любопытные и блестящие дочери, Габриэлла и София, которые являются двумя из моих самых больших поклонников. Элла предлагает всем, кто говорит о программировании слушать мои подкасты, а Фия щеголяла наклейкой кода теста на рюкзаке, которую она взяла во второй класс.
Есть еще столько людей, которых нужно благодарить.
Мой редактор, Кэтрин Дворжак, помогла мне сформировать кучу случайных идей и тем в сплоченную прогрессию, и является причиной, почему ЭТО книга, а не серия сообщений в блоге, скрепленных вместе. Я вошел в этот проект как блоггер, и слишком привязался к множеству заголовков, подзаголовков и пунктам списка, и Кэти терпеливо вела меня, чтобы я смог стать писателем получше.
Спасибо Сюзанне Дэвидсон Пфальцер, Энди Ханту и остальной части «Pragmatic Bookshelf» за то, что у меня есть шанс.
Технические рецензенты держали меня честным в pytest, но также и в стиле Python, и являются причиной того, что примеры кода соответствуют PEP 8. Спасибо Оливеру Бествальтеру, Флориану Брухину, Флорису Бруиногу, Марку Гуди, Питеру Хэмптону, Дэйву Ханту, Аль Кринкеру, Локешу Кумару Макани, Бруно Оливейре, Ронни Пфанншмидту, Рафаэлю Пьерзине, Лучано Рамальо, Фрэнку Руису и Дмитрию Зиновьеву. Многие из этого списка также являются разработчиками ядра pytest и/или поддерживающими невероятные плагины pytest.
Особая благодарность Лучано. Написав эту книгу, я первые четыре главы отправил нескольким рецензентам. Лучано был одним из них, и его обзор был самым трудным для чтения. Я не думаю, что я следовал всем его советам, но из-за его замечаний я пересмотрел и переписал большую часть первых трех глав и изменил кое что в остальной части книги.
Спасибо всей команде pytest-dev за создание такого крутого инструмента тестирования. Спасибо Оливеру Бествальтеру, Флориану Брухину, Флорису Бруйноохе, Дэйву Ханту, Хольгеру Крекелю, Бруно Оливейре, Ронни Пфанншмидту, Рафаэлю Пьерзине и многим другим за ответы на мои вопросы о жизни на протяжении многих лет.
И последнее, но не менее важное: мне нужно поблагодарить людей, которые поблагодарили меня. Воспользовались случаем, чтобы сообщить мне на email о том, что мой труд, спас их время и облегчил работу. Это круто, и радует меня! Спасибо!
Brian Okken
сентябрь 2017
Предисловие
Использование Python возрастает не только в разработке программного обеспечения, но и в таких областях, как анализ данных, научные исследования, испытания и измерения, а также в других отраслях промышленности. Развитие Python во многих критических областях также сопровождается желанием правильно, эффективно и результативно проводить тесты программного обеспечения, чтобы убедиться, что программы работают правильно и дают правильные результаты. Кроме того, все больше и больше проектов программного обеспечения охватывают непрерывную интеграцию и включают фазу автоматизированного тестирования, поскольку циклы выпуска сокращаются, а тщательное ручное тестирование все более сложных проектов просто неосуществимо. Команды должны иметь возможность доверять тестам, выполняемым серверами непрерывной интеграции которые сообщают им, могут ли они доверять своему программному обеспечению настолько, чтобы выпускать его.
Введите pytest.
Что такое pytest?
Надежный инструмент тестирования Python, pytest может быть использован для всех типов и уровней тестирование программного обеспечения. pytest может быть использован командами разработчиков, QA команд, независимых групп тестирования, лиц практикующих TDD, и проекты с открытым исходным кодом. Фактически, проекты по всему интернету переключились с unittest или nose на pytest, включая Mozilla и Dropbox. Почему? Потому что pytest предлагает мощные функции, такие как перезапись "assert", сторонние модели плагинов и мощную, но простую fixture model, которая не имеет себе равных в любой другой структуре тестирования.
pytest-это платформа для тестирования программного обеспечения, что означает, что pytest-это программа командной строки. Инструмент, который автоматически находит написанные тесты, запускает тесты и пишет отчеты с результатом. Он имеет библиотеку примочек, которые можно использовать в тестах, чтобы помочь вам тестировать более эффективно. Он может быть расширен путем написания собственных плагинов или установки сторонних. Его можно использовать для тестирования дистрибутивов Python. И он легко интегрируется с другими инструментами, такими как непрерывная интеграция и веб автоматизация.
Вот несколько причин, почему pytest выделяется среди многих других тестов интегрированные системы:
- Простые тесты легко написать в pytest.
- Complex tests еще проще писать.
- Тесты легко читаются.
- Тесты легко читаются. (Так важно, что это указано дважды.)
- Вы можете начать работу в считанные секунды.
- Для провала теста используется
assert
, а неself.assertEqual()
илиself.assertLessThan()
. Просто assert! - Можно использовать pytest для запуска тестов, написанных для unittest или nose.
pytest активно развивается и поддерживается страстным и растущим сообществом. Он настолько расширяем и гибок, что легко вписывается в ваш рабочий процесс. И поскольку он установлен отдельно от вашей версии Python, вы можете использовать ту же самую последнюю версию pytest на устаревших Python 2 (2.6 и выше) и Python 3 (3.3 и выше).
Изучение pytest при тестировании примера приложения
Вы бы хотели изучать pytest, тестируя глупые примеры, которые никогда не встретите в реальной жизни? Я тоже. Мы не собираемся делать это в этой книге. Взамен, мы собираемся написать тесты для проекта, который, я надеюсь, имеет много похожего с приложениями, которые вы будете тестировать после прочтения этой книги.
Проект Tasks
Приложение, которое мы рассмотрим, называется Tasks (задачи). Tasks-это минимальное приложение для отслеживания задач с интерфейсом командной строки. Он имеет достаточно общего со многими другими типами приложений, которые, я надеюсь, вы можете легко увидеть, как концепции тестирования, которые вы изучаете при разработке тестов против задач, применимы к вашим проектам сейчас и в будущем.
Хотя Tasks имеет интерфейс командной строки (CLI), CLI взаимодействует с остальной частью кода через интерфейс прикладного программирования (API). API — это интерфейс, на который мы будем направлять большую часть нашего тестирования. API взаимодействует с уровнем управления базой данных, который взаимодействует с базой данных документа — MongoDB или TinyDB. Тип базы данных настраивается при инициализации базы данных. Прежде чем сосредоточиться на API, давайте рассмотрим сами задачи, инструмент командной строки, который представляет пользовательский интерфейс для задач.
Вот пример сеанса:
$ tasks add 'do something' --owner Brian
$ tasks add 'do something else'
$ tasks list
ID owner done summary
-- ----- ---- -------
1 Brian False do something
2 False do something else
$ tasks update 2 --owner Brian
$ tasks list
ID owner done summary
-- ----- ---- -------
1 Brian False do something
2 Brian False do something else
$ tasks update 1 --done True
$ tasks list
ID owner done summary
-- ----- ---- -------
1 Brian True do something
2 Brian False do something else
$ tasks delete 1
$ tasks list
ID owner done summary
-- ----- ---- -------
2 Brian False do something else
$
Прим.переводчика: В случае использования платформы Windows, я столкнулся с несколькими проблемами при испытании приведенного сеанса.
- Должна быть создана папка для базы TinyDB с именем
tasks_db
в папке вашего пользователя. Напримерc:UsersUser_1tasks_db
- Используйте кавычки вместо апострофов. Иначе, получаем такую ошибку.
$ tasks add 'do something else'
Usage: tasks add [OPTIONS] SUMMARYError: Got unexpected extra arguments (something else')
Это не самое сложное приложение для управления задачами, но достаточно сложное что бы использовать для изучения тестирования.
Стратегия тестирования
Хотя pytest годится для модульного тестирования (Unit Testing), интеграционного тестирования (Integration Testing), системного (System Testing) или end-to-end тестирования и функционального тестирования, стратегия тестирования проекта Tasks фокусируется главным образом на subcutaneous functional testing. Ниже приведены некоторые полезные определения:
- Модульный тест (Unit test): тест, который проверяет небольшой фрагмент кода, например функцию или класс, в изоляции от остальной системы. Я рассматриваю тесты в Главе 1, Начало работы с pytest, на стр. 1, для выполнения модульных тестов Структура данных задач.
- Интеграционный тест (Integration Testing): тест, который проверяет больший кусок кода, может включать несколько классов или подсистемы. Главным образом ярлык используемый для некоторого испытания побольше чем модульный тест, но меньше системного теста.
- Системный тест (end-to-end): тест, который проверяет всю тестируемую систему в среде, максимально приближенной к среде конечного пользователя.
- Функциональный тест (Functional testing): Тест, который проверяет один кусок функциональности системы. Тест, который проверяет, насколько хорошо мы добавляем, удаляем или обновляем элемент задачи в Tasks, является функциональным тестом.
- Subcutaneous test: Тест, который выполняется не для конечного пользовательского интерфейса, а для интерфейса, расположенного чуть ниже поверхности. Поскольку большинство тестов в этой книге тестируются на уровне API, а не CLI, они квалифицируются как подкожные(Subcutaneous) тесты.
Как организована эта книга
В главе 1 «Приступая к работе с pytest» на стр. 1 вы установите pytest и подготовитесь к его использованию. Затем вы возьмете одну часть проекта Tasks — структуру данных, представляющую одну задачу (namedtuple called Task), и используйте ее для тестирования примеров. Вы узнаете, как запустить pytest с несколькими тестовыми файлами. Вы увидите многие популярные и чрезвычайно полезные параметры командной строки для pytest, такие как возможность повторного запуска тестовых сбоев, остановки выполнения после первого отказа, управления трассировкой стека и многостраничной версией тестового запуска и многое другое.
В главе 2, "Создание тестовых функций", на странице 23, Вы установите Tasks локально с помощью pip и посмотрите, как структурировать тесты в проекте Python. Вы должны сделать это, чтобы приступить к написанию тестов для реального приложения. Все примеры в этой главе запускают тесты для установленного приложения, включая запись в базу данных. Фактические функции тестирования находятся в центре внимания этой главы, и вы узнаете, как эффективно использовать assert
в тестах. Вы также узнаете о маркерах. Функции, которая позволяет отметить много тестов, которые будут выполняться одновременно, отметить тесты, которые будут пропущены, или указать pytest, что мы уже знаем, что некоторые тесты потерпят неудачу. Я расскажу о том, как выполнять только некоторые тесты, не только с маркерами, но и структурируя наш тестовый код в каталоги, модули и классы, и как запускать эти подмножества тестов.
Не все тестовые коды входят в тестовые функции. В главе 3, "pytest Fixtures", на стр. 49, вы узнаете, как помещать тестовые данные в тестовые фикстуры, а также настраивать и разрывать код. Настройка состояния системы (или подсистемы или отдельной единицы) является важной частью тестирования программного обеспечения. Вы изучите этот аспект фикстур pytest, чтобы помочь инициализировать базу данных проекта Tasks и предварительно заполнить тестовыми данными для некоторых тестов. Fixtures(Фикстуры) — невероятно мощная часть pytest, и вы научитесь эффективно их использовать, чтобы еще больше уменьшить дублирование тестового кода и помочь сделать ваш тестовый код невероятно удобочитаемым и поддерживаемым. Pytest-фикстуры также параметризуемы, аналогично тестовым функциям, и вы будете использовать эту функцию, чтобы иметь возможность запускать все ваши тесты как с TinyDB, так и с MongoDB, серверные части базы данных, поддерживаемые Tasks.
В главе 4, "Builtin Fixtures", на странице 71, вы увидите некоторые встроенные fixtures, поставляемых в pytest. Вы узнаете, как pytest builtin fixtures могут отслеживать временные каталоги и файлы для вас, помочь вам проверить вывод из тестируемого кода, использовать monkey patches, проверить наличие предупреждений, и многое другое.
В главе 5, "Плагины", на странице 95, вы узнаете, как добавить параметры командной строки в pytest, изменить вывод pytest и поделиться настройками pytest, включая fixtures, с другими пользователями через написание(writing), упаковку(packaging) и распространение(distributing) собственных плагинов. Плагин, который мы разрабатываем в этой главе, используется, чтобы сотворить ошибки тестирования, которые мы видим при тестировании задач, немного приятнее. Вы также узнаете, как правильно тестировать тестовые Плагины. Что за meta? И на всякий случай, если вы недостаточно вдохновлены этой главой, чтобы написать свои собственные плагины, я подобрал кучу отличных плагинов, чтобы показать, что возможно в Приложении 3, "Plugin Sampler Pack", на странице 163.
Говоря о кастомизации, в главе 6, "Конфигурация", на стр. 113, вы узнаете, как настроить запуск pytest по умолчанию для вашего проекта с помощью файлов конфигурации. С файлом pytest.ini, вы можете делать такие вещи, как хранение параметров командной строки, так что вам не придется вводить их все время, скАжите pytest, чтобы не заглядывать в определенные каталоги для тестовых файлов, укажите минимальную версию pytest, на которую написаны ваши тесты, и многое другое. Эти элементы конфигурации могут быть помещены в tox.ini или setup.cfg.
В заключительной главе, Глава 7, используя pytest с другими инструментами, на странице 125, вы увидите, как вы можете взять уже мощный pytest и перегрузить свое тестирование дополнительными инструментами. Вы запустите проект Tasks на несколько версий Python с tox. Вы протестируете CLI Tasks, не выполняя остальную часть системы с mock. Вы будете использовать coverage.py чтобы проверить, не тестируется ли исходный код проекта задач. Вы будете использовать Jenkins для запуска наборов тестов и отображения результатов с течением времени. И, наконец, вы увидите, как pytest можно использовать для запуска тестов unittest, а также для обмена фикстурами стиля pytest с тестами unittestbased.
Что вам нужно знать
Python
You don’t need to know a lot of Python. The examples don’t do anything super weird or fancy.
Вам не нужно быть гуру Python. Примеры не делают ничего сверхъестественного или причудливого.
pip
Вы должны использовать pip для установки плагинов pytest и самого pytest. Если вы хотите обновить pip, ознакомьтесь с Приложением 2, pip, на странице 159.
Командная строка
Я написал эту книгу и запечатлил примеры вывода с помощью bash на Mac laptop. Тем не менее, единственные команды, которые я использую в bash, — это cd для перехода в определенный каталог и конечно pytest. Так как cd существует в Windows cmd.exe и во всех оболочках unix, которые я знаю, все примеры должны быть доступны для запуска в любом терминальном приложении, которое вы решите использовать.
Вот и все. Вам не нужно быть экспертом по программированию, чтобы начать писать автоматические тесты с помощью pytest.
Примеры кода и интернет-ресурсы
Примеры в этой книге написаны с использованием Python 3.6 и pytest 3.2. pytest 3.2 поддерживает Python 2.6, 2.7 и Python 3.3+.
Исходный код для проекта Tasks, а также для всех тестов, показанных в этой книге, доступен по ссылке на веб-странице книги в pragprog.com. Вам не нужно загружать исходный код, чтобы понять тестовый код; тестовый код представлен в удобной форме в примерах. Но что бы следовать вместе с задачами проекта, или адаптировать примеры тестирования, чтобы проверить свой собственный проект (руки у вас развязаны!), вы должны перейти на веб-страницу книги, чтобы скачать работу. Там же, на веб-странице книги есть ссылка на сообщение errata и дискуссионный форум.
Я программировал более двадцати пяти лет, и ничто не заставляло меня любить писать тестовый код так сильно, как pytest. Я надеюсь, что вы многому научитесь из этой книги, и я надеюсь, что в конечном итоге вы полюбите тестовый код так же, как и я.
Автор: Александр Драгункин