Создание тестов для REST API на Python с использованием запросов. Часть 2: тесты, управляемые через данные |
08.07.2020 00:00 |
Автор: Баз Дейкстра (Bas Djikstra) Создание тестов для REST API на Python с использованием запросов. Часть 1: базовые тесты Недавно я провел свой первый трехдневный курс "Python для тестировщиков". Одна из тем, раскрытых в этом курсе – это создание тестов для REST API с использованием библиотеки запросов Python и фреймворка юнит-тестирования pytest. В этой короткой серии статей я хочу исследовать библиотеку запросов Python и ее использование для создания тестов REST API. Это вторая часть серии, в которой мы рассмотрим создание тестов, управляемых через данные. О тестировании, управляемом через данные Прежде чем начать, давайте быстро разберемся, что такое тесты, управляемые через данные. При создании автотестов вы зачастую пожелаете протестировать ту же самую бизнес-логику, алгоритм, расчет или поток приложения несколько раз с различными вводными данными и ожидаемыми результатами. Технически этого можно добиться, просто скопировав имеющийся тест и изменив нужные данные. С точки зрения поддерживаемости это, однако, не лучшая идея. Вместо этого лучше написать управляемый через данные тест: он получает свои тестовые данные из источника данных, и проводит несколько итераций согласно строкам (или записям) в этом источнике. Создание объекта тестовых данныхБольшая часть фреймворков для юнит-тестирования поддерживает тестирование, управляемое через данные, и pytest не исключение. Прежде чем разобраться, как создать тест, управляемый через данные, в Python, создадим наш источник тестовых данных. В Python это легко – просто создадим список наборов значений, где каждый набор соответствует одной итерации теста ("тест-кейса", если вам так больше нравится).
Мы будем прогонять три итерации одного и того же теста – получать данные о геолокации для заданного кода страны и индекса (первые два элемента в наборе), а затем убеждаться, что соответствующее название места, возвращенное API, соответствует ожидаемому (третий элемент в наборе). Создание теста, управляемого через данные, в pytestТеперь, когда у нас есть тест-данные, давайте превратим существующий тест из первой части цикла статей в тест, управляемый через данные.
Pytest поддерживает тестирование через данные путем встроенного маркера @pytest.mark.parametrize. Этот маркер принимает два аргумента – первый говорит pytest, как (в каком порядке) присваивать элементы набора из источника данных аргументам тестового метода, а второй аргумент – это сам объект тестовых данных. Тест-методы, которые мы рассматривали в прошлый раз, аргументов не имели, но так как мы скармливаем тестам данные извне, нам нужно определить три аргумента для тест-метода: код страны, индекс, и ожидаемое название места. Затем эти аргументы можно использовать в теле тест-метода – первые два как значения параметра пути в вызове API, а последний – как значение ожидаемого результата, извлеченного из JSON-ответа. Запуск тестаПри прогоне этого теста мы увидим, что несмотря на то, что тест-метод только один, Pytest распознает и прогоняет три теста. Даже лучше – он прогоняет один и тот же тест три раза, по разу для каждого набора в объекте тест-данных. С моей точки зрения, это демонстрация мощи тестирования через данные. Мы можем провести столько итераций, сколько требуется для конкретного теста, и не дублировать код – надо только сообщить pytest, откуда брать тестовые данные. Нужна дополнительная итерация с другими значениями? Просто добавьте запись в объект тестовых данных. Хотите обновить или убрать тест-кейс? Вы знаете, что делать. Другая полезная штука с тестированием через данные при помощи pytest: когда падает одна из итераций, pytest сообщит, какая именно упала, и какие конкретно значения использовались. Создание внешнего источника данныхВ этом примере тестовые данные все еще были жестко прописаны в коде теста. Это может быть неоптимальным способом работы. Что, если бы мы могли определить тестовые данные во внешнем источнике данных и приказать pytest считывать их оттуда? Для примера создадим .csv-файл, содержащий те же данные, что и объект тест-данных, который мы видели ранее: country_code,zip_code,expected_place_name us,90210,Beverly Hills ca,B2A,North Sydney South Central it,50123,Firenze Для использования этих данных в тесте нужно написать метод Python, считывающий данные из файла и возвращающий их в совместимом с маркером parametrize формате. Python хорошо поддерживает работу с .csv-файлами благодаря встроенной библиотеке csv:
Этот метод открывает .csv-файл в режиме чтения, пропускает строку заголовков, добавляет все прочие строки в список значений тестовых данных test_data по одному, и возвращает объект тестовых данных. Тест-метод теперь требует обновления, дабы не использовать жестко закодированные данные, забирая вместо этого результат работы метода, читающего данные из csv-файла:
Запуск обновленного теста покажет, что и в этом случае прогоняется три итерации теста. Конечно, вы можете использовать и другие источники, не только csv – например, результат запроса к базе данных, XML или JSON. Если вы способны написать метод, возвращающий список наборов тестовых значений – все в ваших руках. В следующий раз мы продолжим исследование работы с JSON и XML в запросах API и теле ответов. Самостоятельное использование примеровПримеры кода из этой статьи можно найти на моей странице GitHub. Если вы скачали проект и (при условии правильной установки Python) запустили pip install -r requirements.txt из корневой папки проекта python-requests для установки нужных библиотек, то вы сможете прогнать тесты самостоятельно. |