Что такое API
Содержание
— А зачем это мне? Я вообще-то web тестирую! Вот если пойду в автоматизацию, тогда да… Ну, еще это в enterprise тестируют, я слышал…
А вот и нет! Про API полезно знать любому тестировщику. Потому что по нему системы взаимодействуют между собой. И это взаимодействие вы видите каждый день даже на самых простых и захудалых сайтах.
Любая оплата идет через API платежной системы. Купил билет в кино? Маечку в онлайн-магазине? Книжку? Как только жмешь «оплатить», сайт соединяет тебя с платежной системой.
Но даже если у вас нет интеграции с другими системами, у вас всё равно есть API! Потому что система внутри себя тоже общается по api. И пока фронт-разработчик усиленно пилит GUI (графический интерфейс), вы можете:
Что такое API
API (Application programming interface) — это контракт, который предоставляет программа. «Ко мне можно обращаться так и так, я обязуюсь делать то и это».
Если переводить на русский, это было бы слово «договор». Договор между двумя сторонами, как договор на покупку машины:
API — набор функций
Когда вы покупаете машину, вы составляете договор, в котором прописываете все важные для вас пункты. Точно также и между программами должны составляться договоры. Они указывают, как к той или иной программе можно обращаться.
Соответственно, API отвечает на вопрос “Как ко мне, к моей системе можно обратиться?”, и включает в себя:
Тут вы можете мне сказать:
— Хмм, погоди. Операция, данные на входе, данные на выходе — как-то всё это очень сильно похоже на описание функции!
Если вы когда-то сталкивались с разработкой или просто изучали язык программирования, вы наверняка знаете, что такое функция. Фактически у нас есть данные на входе, есть данные на выходе, и некая магия, которая преобразует одно в другое.
И да! Вы будете правы в том, что определения похожи. Почему? Да потому что API — это набор функций. Это может быть одна функция, а может быть много.
Как составляется набор функций
Да без разницы как. Как разработчик захочет, так и сгруппирует. Например, можно группировать API по функционалу. То есть:
Можно не группировать вообще, а делать одно общее API.
Можно сделать одно общее API, а остальные «под заказ». Если у вас коробочный продукт, то в него обычно входит набор стандартных функций. А любые хотелки заказчиков выносятся отдельно.
Получается, что в нашей системе есть несколько разных API, на каждое из которых у нас написан контракт. В каждом контракте четко прописано, какие операции можно выполнять, какие функции там будут
И конечно, функции можно переиспользовать. То есть одну и ту же функцию можно включать в разные наборы, в разные апи. Никто этого не запрещает.
Получается, что разработчик придумывает, какое у него будет API. Либо делает общее, либо распределяет по функционалу или каким-то своим критериям, и в каждое апи добавляет тот набор функций, который ему необходим.
При чем тут слово «интерфейс»
— Минуточку, Оля! Ты же сама выше писала, что API — это Application programming interface. Почему ты тогда говоришь о контракте, хотя там слово интерфейс?
Да потому, что в программировании контракт — это и есть интерфейс. В классическом описании ООП (объектно-ориентированного программирования) есть 3 кита:
Не всегда программа предоставляет именно графический интерфейс. Это может быть SOAP, REST интерфейс, или другое API. Чтобы использовать этот интерфейс, вы должны понимать:
Как вызывается API
Вызвать апи можно как напрямую, так и косвенно.
Вызов API напрямую
1. Система вызывает функции внутри себя
Разные части программы как-то общаются между собой. Они делают это на программном уровне, то есть на уровне API!
Это самый «простой» в использовании способ, потому что автор API, которое вызывается — разработчик. И он же его потребитель! А значит, проблемы с неактуальной документацией нет =)
Шучу, проблемы с документацией есть всегда. Просто в этом случае в качестве документации будут комментарии в коде. А они, увы, тоже бывают неактуальны. Или разработчики разные, или один, но уже забыл, как делал исходное api и как оно должно работать…
2. Система вызывает метод другой системы
А вот это типичный кейс, которые тестируют тестировщики в интеграторах. Или тестировщики, которые проверяют интеграцию своей системы с чужой.
Одна система дергает через api какой-то метод другой системы. Она может попытаться получить данные из другой системы. Или наоборот, отправить данные в эту систему.
Допустим, я решила подключить подсказки из Дадаты к своему интернет-магазинчику, чтобы пользователь легко ввел адрес доставки.
Я подключаю подсказки по API. И теперь, когда пользователь начинает вводить адрес на моем сайте, он видит подсказки из Дадаты. Как это получается:
И, конечно, не забываем про кейс, когда мы разрабатываем именно API-метод. Который только через SOAP и можно вызвать, в интерфейсе его нигде нет. Что Заказчик заказал, то мы и сделали ¯\_(ツ)_/¯
Пример можно посмотреть в Users. Метод MagicSearch создан на основе реальных событий. Хотя надо признать, в оригинале логика еще замудренее была, я то под свой сайт подстраивала.
Но тут фишка в том, что в самой системе в пользовательском интерфейсе есть только обычный поиск, просто строка ввода. Ну, может, парочка фильтров. А вот для интеграции нужна была целая куча доп возможностей, что и было сделано через SOAP-метод.
Функционал супер-поиска доступен только по API, пользователь в интерфейсе его никак не пощупает.
В этом случае у вас обычно есть ТЗ, согласно которому работает API-метод. Ваша задача — проверить его. Типичная задача тестировщика, просто добавьте к стандартным тестам на тест-дизайн особенности тестирования API, и дело в шляпе!
(что именно надо тестировать в API — я расскажу отдельной статьей чуть позднее)
3. Человек вызывает метод
Для примера снова идем в Users. Если мы хотим создать пользователя, надо заполнить уйму полей!
Конечно, это можно сделать в помощью специальных плагинов типа Form Filler. Но что, если вам нужны адекватные тестовые данные под вашу систему? И на русском языке?
Заполнение полей вручную — грустно и уныло! А уж если это надо повторять каждую неделю или день на чистой тестовой базе — вообще кошмар. Это сразу первый приоритет на автоматизацию рутинных действий.
И в данном случае роль автоматизатора выполняет… Postman. Пользователя можно создать через REST-запрос CreateUser. Один раз прописали нормальные “как настоящие” данные, каждый раз пользуемся. Профит!
Вместо ручного заполнения формы (1 минута бездумного заполнения полей значениями «лпрулпк») получаем 1 секунду нажатия на кнопку «Send». При этом значения будут намного адекватнее.
А еще в постмане можно сделать отдельную папку подготовки тестовой базы, напихать туда десяток запросов. И вот уже на любой базе за пару секунд вы получаете столько данных, сколько вручную вбивали бы часами!
Если вы нашли баг и не понимаете, на кого его вешать — разработчика front-end или back-end, уберите все лишнее. Вызовите метод без графического интерфейса. А еще вы можете тестировать логику программы, пока интерфейс не готов или сломан.
4. Автотесты дергают методы
Есть типичная пирамида автоматизации:
Слово API как бы намекает на то, что будет использовано в тестах ツ
GUI-тесты — честный тест, робот делает все, что делал бы пользователь. Открывает браузер, тыкает на кнопочки… Но если что-то упадет, будете долго разбираться, где именно.
API-тесты — все то же самое, только без браузера. Мы просто подаем данные на вход и проверяем данные на выходе. Например, можно внести итоговый ответ в эксельку, и пусть робот выверяет ее, правильно ли заполняются данные? Локализовать проблему становится проще.
Unit-тесты — это когда мы проверяем каждую функцию отдельно. Отдельно смотрим расчет для ячейки 1, отдельно — для ячейки 2, и так далее. Такие тесты шустрее всего гоняются и баги по ним легко локализовать.
Косвенный вызов API
Когда пользователь работает с GUI, на самом деле он тоже работает с API. Просто не знает об этом, ему это просто не нужно.
То есть когда пользователь открывает систему и пытается загрузить отчет, ему не важно, как работает система, какой там magic внутри. У него есть кнопочка «загрузить отчет», на которую он и нажимает. Пользователь работает через GUI (графический пользовательский интерфейс).
Но на самом деле под этим графическим пользовательским интерфейсом находится API. И когда пользователь нажимает на кнопочку, кнопочка вызывает функцию построения отчета.
А функция построения отчета уже может вызывать 10 разных других функций, если ей это необходимо.
И вот уже пользователь видит перед собой готовый отчет. Он вызвал сложное API, даже не подозревая об этом!
Что значит «Тестирование API»
В первую очередь, мы подразумеваем тестирование ЧЕРЕЗ API. «Тестирование API» — общеупотребимый термин, так действительно говорят, но технически термин некорректен. Мы не тестируем API, мы не тестируем GUI (графический интерфейс). Мы тестируем какую-то функциональность через графический или программный интерфейс.
Но это устоявшееся выражение. Можно использовать его и говорить “тестирование API”. И когда мы про это говорим, мы имеем в виду:
Когда мы говорим про тестирование API, чаще всего мы подразумеваем тестирование Remote API. Когда у нас есть две системы, находящихся на разных компьютерах, которые как-то между собой общаются.
И если вы видите в вакансии «тестирование API», скорее всего это подразумевает умение вызвать SOAP или REST сервис и протестировать его. Хотя всегда стоит уточнить!
Резюме
API (Application programming interface) — это контракт, который предоставляет программа. «Ко мне можно обращаться так и так, я обязуюсь делать то и это».
Data API
Соглашения
Приняты следующие соглашения при использовании Data API:
Добавить IP-адрес в список разрешенных
Если необходимо разрешить доступ всем IP-адресам, то нужно добавить в список разрешенных 0.0.0.0/0
Если запрос делается из под агента, то его IP адрес должен быть добавлен в белый список клиентского аккаунта
Пользователи API и аутентификация
К пользователям и ключам доступа применяются права доступа аналогичные правам доступа в личном кабинете
Доступ по ключу
Ключи генерируются на уровне пользователя в разделе личного кабинета «Аккаунт» → «Управление пользователями» Существует два типа ключей:
Постоянный ключ имеет неограниченное время действия. Временный ключ имеет конкретную дату окончания действия ключа.
Доступ по логину и паролю
Используется аутентификация с использованием сессий
Отчёт по запросам к API
В личном кабинете «Отчёты»->»Служебные»->»Запросы к API» можно построить отчёт по запросам к API
Базовый URL для доступа к API
Базовый URL для доступа к API соответствует следующему шаблону:
Версионность
Текущая версия Data API 2.0
Если была выпущена новая версия, то старая считается устаревшей и соответственно при обращении к старой версии API в мета-параметрах (см. раздел Мета-параметры) будет возвращаться параметр «current_version_deprecated» со значением «true»
Лимиты и ограничения
Баллы списываются только за успешные запросы, т.е в отчете по запросам к API (см. раздел Отчёт по запросам к API) он помечен как успешный.
Информация о лимитах возвращается во всех ответах в мета-парметрах (см. раздел Мета-параметры) кроме случаев когда лимиты не учитываются;
Лимиты построены по бальной системе, т.е каждый метод имеет свой вес. Вызов метода уменьшает доступные дневные/минутные баллы на размер веса вызываемого метода
Информация о лимитах в мета-параметрах:
| Название параметра | Описание |
|---|---|
| day_limit | Текущий лимит баллов в день |
| day_remaining | Какое количество баллов осталось до достижения дневного лимита |
| day_reset | Время в секундах через которое дневной лимит будет сброшен |
| minute_limit | Текущий лимит баллов за минуту |
| minute_remaining | Какое количество баллов осталось до достижения минутного лимита |
| minute_reset | Время в секундах через которое минутный лимит будет сброшен |
Методы и их стоимость в баллах
Расширение лимитов
Обработка ошибок
Параметры сообщения об ошибке
| Название | Тип | Обязательный | Описание |
|---|---|---|---|
| error | object | да | Объект с содержимым ошибки |
| code | number | да | Не уникальный код ошибки (см. раздел Группы кодов ошибок ) |
| message | string | да | Cообщение об ошибке |
| data | object | да | Объект с деталями ошибки |
| mnemonic | string | да | Уникальный текстовый код ошибки. При обработке ошибок рекомендуется использовать этот параметр. |
| value | string | нет | Содержит то, что передал пользователь без изменений |
В некоторых случаях может отсутствовать. К примеру, обязательный параметр вообще не был заполнен.
Вложенные параметры отображаются через разделитель точка «.»
К примеру: «employee.phone_number»
JSON структура ошибки
Группы кодов ошибок
Список ошибок общих для всех методов
Список ошибок для методов с глаголом get
| Текст ошибки | Код | Мнемоника | Описание |
|---|---|---|---|
| Invalid parameter value | -32602 | invalid_parameter_value | Если в фильтрах было передано некорректное значение для regexp, jsquery или любых значений не соответствующих документации |
| Sort by parameter is prohibited | -32602 | sort_prohibited | Сортировка по параметру запрещена и невозможна, так как параметр для сортировки не находится в списке разрешенных для сортировки |
| Filter by parameter is prohibited | -32602 | filter_prohibited | Фильтрация по параметру запрещена и невозможна, так как параметр для фильтрации не находится в списке разрешенных для фильтрации |
| Max value of requested date interval is 3 months | -32602 | date_interval_limit_reached | Если в запросе период между указанными датами в date_from и date_till превышает 3 месяца. В основном ошибка актуальна только для методов получения отчетов, но не для всех. |
Список ошибок общих для методов с глаголом delete
| Текст ошибки | Код | Мнемоника | Описание |
|---|---|---|---|
| Entity not found | -32602 | entity_not_found | Если передан уникальный идентификатор сущности, которая не найдена |
| You have interdependet entities | -32602 | dependency_error | Удаляемая сущность используется в других сущностях. Чтобы удалить, необходимо убрать удаляемую сущность из всех возможных мест где она используется |
| Permission denied | -32602 | forbidden | Удалить сущность невозможно так как она системная, к примеру группа «Черный список» в адресной книге |
Список ошибок общих для методов с глаголом create и update, set, unset
| Текст ошибки | Код | Мнемоника | Описание |
|---|---|---|---|
| Entity not found | -32602 | entity_not_found | Если передан уникальный идентификатор сущности, которая не найдена |
| Duplicate entity | -32602 | duplicate_entity | Если сущность уже существует |
| Campaign is inactive | -32602 | campaign_is_inactive | Рекламная кампания не активна |
| Invalid date time | -32602 | invalid_date_time | Не валидная дата или время, смотрите описание метода |
| A new data limit has been exceeded | -32602 | data_limit_exceeded | Ошибка возникает в случае, если было достигнуто максимальное количество данных. |
| Action is not allowed for your tariff plan. You need contact support service or change your tariff plan settings in your account | -32602 | tariff_restrictions | Любые ограничения тарифного плана |
| This value is already used by another entity | -32602 | already_in_use | Значение указанного параметра уже используется в другой сущности. К примеру, виртуальный номер уже используется в другой рекламной кампании. |
Групповые операции
Функционал не поддерживается
Принцип именования методов
Имя JSON-RPC метода состоит из двух частей разделенных точкой: глагола и имени объекта.
Имя метода должно начинаться с глагола, отражающего суть операции.
Глаголы используемые в именовании методов
| Глагол | Описание |
|---|---|
| create | Добавляет сущность. |
| get | Возвращает список отсортированных и отфильтрованных данных с помощью критериев фильтрации и методов сортировки. К запросу возможно применить лимит и постраничный вывод на количество получаемых данных (см. раздел Постраничный вывод). С помощью критериев фильтрации может быть так же получена одна запись, по ёё уникальному идентификатору (см. раздел Критерии фильтрации). В специальном мета-параметре возвращается общее количество записей (см. раздел Мета-параметры). С помощью специального параметра можно указать какие поля возвращать в ответном сообщении (см. раздел Представление возвращаемых данных). |
| update | Обновляет сущность с определённым идентификатором. |
Возможно частичное обновление параметров
При обновлении массивов обновляется весь массив целиком, т.е все элементы которые не были переданы удаляются.
Для зануления необязательного параметра нужно передать null
Критерии фильтрации
Возможные ошибки при фильтрации
| Текст | Код | Мнемоника | Описание |
|---|---|---|---|
| Filter by parameter is prohibited | -32602 | filter_prohibited | Фильтрация по параметру запрещена и невозможна, так как параметр для фильтрации не находится в списке разрешенных для фильтрации |
| Unexpected method parameter(s) | -32602 | unexpected_parameters | Передан ошибочный параметр или параметр, которого не существует |
Пример JSON структуры простого фильтра
Получаем список записей у которых поле «name» имеет имя «Bob»
Пример JSON структуры дерева фильтров с одним уровнем вложенности
Получаем список записей у которых поле «name» имеет имя «Bob» и его возраст 25 лет
Пример JSON структуры дерева фильтров с двойным уровнем вложенности
Получаем список записей у которых поле «name» имеет имя «Bob» и его возраст 25 лет или список записей у которых поле «name» имеет имя «Dexter» и его возраст 2 года
Пример JSON структуры дерева фильтров с тройным уровнем вложенности
Условие запроса ((addv_comp_id = 10 or addv_comp_id = 12) and (tag_id = 1 or tag_id = 5)) or visitor_id = 14 or (date_from = 2015-12-14 and date_till = 2015-12-16)
Операторы фильтрации
| Оператор | Описание | Учёт регистра строк | Тип данных |
|---|---|---|---|
| = | Равно | да | number, string, null, boolean, iso8601, enum |
| != | Не равно | да | number, string, null, boolean, iso8601, enum |
| Меньше чем | — | number, iso8601 | |
| > | Больше чем | — | number, iso8601 |
| Меньше или равно | — | number, iso8601 | |
| >= | Больше или равно | — | number, iso8601 |
| like | Начинается с, Заканчивается на, Содержит |
Сортировка данных
Сортировка данных применяется только к глаголу «get» (см. раздел «Глаголы используемые в именовании методов») с помощью массива объектов сортировки со следующими примитивами:
Список полей по которым можно производить сортировку определяется индивидуально для каждого метода.
Возможные ошибки при сортировки
| Текст ошибки | Код | Мнемоника | Описание |
|---|---|---|---|
| Sort by parameter is prohibited | -32602 | sort_prohibited | Сортировка по параметру запрещена и невозможна, так как параметр для сортировки не находится в списке разрешенных для сортировки |
| Unexpected method parameter(s) | -32602 | unexpected_parameters | Передан ошибочный параметр или параметр, которого не существует |
Постраничный вывод
Постраничный вывод может быть применён к глаголу «get» (см. раздел «Глаголы используемые в именовании методов»). Для выполнения пагинации данных используются следующие параметры:
| Параметр | Значение по умолчанию | Допустимое значение | Описание |
|---|---|---|---|
| offset | 0 | 100 000 | Сдвиг, определяет с какого номера записи возвращать «limit» записей |
| limit | 1000 | 10 000 | Размер возвращаемых данных (количество записей) |
Мета-параметры
Возвращаются при использовании глагола «get» (см. раздел «Глаголы используемые в именовании методов»).
Присутствуют как в ошибочном, так и в успешном ответе
Параметр «api_version» возвращается только для версий которые deprecated.
Представление возвращаемых данных
Отдельный список возвращаемых столбцов
В глаголе получения данных «get» (см. раздел «Глаголы используемые в именовании методов») может быть указан специальный необязательный примитив «fields» с типом массив, который может содержать список полей которые необходимо показать в выводе. Если примитив «fields» не используется, то в выводе показываются все поля по умолчанию для вызываемого метода.
Список полей индивидуален для каждого метода.




