84

Автоматизация функционального тестирования REST API

Embed Size (px)

Citation preview

Page 1: Автоматизация функционального тестирования REST API
Page 2: Автоматизация функционального тестирования REST API

Автоматизация функционального тестирования REST API

секреты, тонкости и подводные камни

Page 3: Автоматизация функционального тестирования REST API

Павел Асанов

QA Lead

Page 4: Автоматизация функционального тестирования REST API

90 городов

700 тыс. пользователей

12 млн просмотров

1 млн отзывов

3 млн посетителей

Page 5: Автоматизация функционального тестирования REST API
Page 6: Автоматизация функционального тестирования REST API
Page 7: Автоматизация функционального тестирования REST API
Page 8: Автоматизация функционального тестирования REST API
Page 9: Автоматизация функционального тестирования REST API

API как продукт

Page 10: Автоматизация функционального тестирования REST API

API как продукт

80%

20%

Page 11: Автоматизация функционального тестирования REST API

Регрессия

3 месяца 5 минут

Page 12: Автоматизация функционального тестирования REST API

● Ресурсы, однозначно определяемые по URL

● Представления ресурсов (JSON)

● Методы работы с ресурсами

REST - это...

POST /reviews GET /reviews/666PUT /reviews/666PATCH /reviews/666DELETE /reviews/666

Page 13: Автоматизация функционального тестирования REST API

Что тестируем?

Page 14: Автоматизация функционального тестирования REST API

1. Логика

Page 15: Автоматизация функционального тестирования REST API
Page 16: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гость

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

приватныйконтент

пользователь

аксесс токен

Page 17: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гость

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

201

Авторизованный пользователь добавляет отзыв с фото

приватныйконтент

пользователь

аксесс токенPOST

Page 18: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гость

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

200

Авторизованный владелец Бизнес-аккаунта запрашивает приватное обращение

приватныйконтент

пользователь

аксесс токен

GET

Page 19: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гость

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

401

Гость добавляет отзыв

приватныйконтент

пользователь

аксесс токен

POST

Page 20: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гость

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

403

Авторизованный пользователь запрашивает чужое приватное обращение

приватныйконтент

пользователь

аксесс токен

GET

Page 21: Автоматизация функционального тестирования REST API

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

невалидный протокол

параметры запроса

скрытыйобычный скрытый с особым типом

авторизованный гостьаксесс токен

БАК

удалённыйзаблокированный

забаненный

филиал БАК

автор неактивированный удалённый

обычный

корректные

с фото

невалидные значения

параметров

невалидные типы

параметров

БАК

expired

другой юзер

500 400 400 404

Невалидный запрос

приватныйконтент

пользователь

Page 22: Автоматизация функционального тестирования REST API

2. Данные и их формат

Page 23: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

Page 24: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

точное значение

Page 25: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

точное значение

тип значения и его диапазон

Page 26: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

точное значение

enum

тип значения и его диапазон

Page 27: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

точное значение

enum

тип значения и его диапазон

формат значения

Page 28: Автоматизация функционального тестирования REST API

{code: 200status: "success"review: {

filial_id: "985690699651034"

text: "Для меня Code Fest - это глоток свежего воздуха. Только надо баги пофиксить."

is_recommended: false

project_id: 1

source: "flamp"

rating: 4

date_created: "2011-03-28T05:30:50+04:00"

user_id: 171

photo: null

}}

точное значение

наличие атрибута

enum

тип значения и его диапазон

формат значения

Page 29: Автоматизация функционального тестирования REST API

3. Изменение состояния системы

Page 30: Автоматизация функционального тестирования REST API

● После DELETE сущность стала недоступна

● После логаута access token удаляется

Page 31: Автоматизация функционального тестирования REST API

● После DELETE сущность стала недоступна

● После логаута access token удаляется

запрос сущности возвращает 404

Page 32: Автоматизация функционального тестирования REST API

● После DELETE сущность стала недоступна

● После логаута access token удаляется

запрос с данным токеном возвращает 401

запрос сущности возвращает 404

Page 33: Автоматизация функционального тестирования REST API

● После DELETE сущность стала недоступна

● После логаута access token удаляется

запрос с данным токеном возвращает 401или

запрос сущности возвращает 404

access token отсутствует в БД

Page 34: Автоматизация функционального тестирования REST API

Глава первая, в которой мы знакомимся с JSON-schema

Page 35: Автоматизация функционального тестирования REST API

JSON-схема — это…

1) готовая документация + примеры

Page 36: Автоматизация функционального тестирования REST API

header: "Информация об отзыве",description: "Информация об отзыве",request: { type: "GET", url: "https://flamp.ru/api/2.0/reviews/{id}", properties: {

id: { type: "integer", required: true,

examples: ["1"], description: "Идентификатор отзыва" }

}},

Page 37: Автоматизация функционального тестирования REST API

response: { type: "object", required: true, properties: {

code: "{{ common/code }}", status: "{{ common/status }}", review: "{{ objects/review }}"

}},

...

Page 38: Автоматизация функционального тестирования REST API

2) валидация запроса на сервере

Page 39: Автоматизация функционального тестирования REST API

3) валидация ответа на сервере в dev-режиме

Page 40: Автоматизация функционального тестирования REST API

+ простейший smoke-тест+ полная проверка формата

Page 41: Автоматизация функционального тестирования REST API

+ простейший smoke-тест+ полная проверка формата

- white-box- схема может содержать ошибки- нельзя использовать на продакшне

Page 42: Автоматизация функционального тестирования REST API

Глава вторая, в которой мы добавляем assertions в JSON-

schema

Page 43: Автоматизация функционального тестирования REST API

assertions: [ {

name: "View Review #1", request: { id: 1 }, response: { status: "success", review: {

id: 1, date_created: "_is_datetime", date_edited: "_is_datetime|null"

} }

},]

Page 44: Автоматизация функционального тестирования REST API

assertions: [{ name: "View Review #99999999", request: { id: 99999999 }, response: { status: "error" }

}]

Page 45: Автоматизация функционального тестирования REST API

Flamposcope

Page 46: Автоматизация функционального тестирования REST API

+ smoke testing+ выполняется ~20 сек+ тесты пишет разработчик

Page 47: Автоматизация функционального тестирования REST API

+ smoke testing+ выполняется ~20 сек+ тесты пишет разработчик

- только GET- захардкоженные данные- тесты пишет разработчик

Page 48: Автоматизация функционального тестирования REST API

Глава третья, в которой мы хотели прикрутить

к JSON-схеме UI

Page 49: Автоматизация функционального тестирования REST API
Page 50: Автоматизация функционального тестирования REST API
Page 51: Автоматизация функционального тестирования REST API

+ удобный UI+ нет кода+ автоподстановка из схемы

Page 52: Автоматизация функционального тестирования REST API

+ удобный UI+ нет кода+ автоподстановка из схемы

- серый ящик- фикстуры- поддержка UI

Page 53: Автоматизация функционального тестирования REST API

Глава четвёртая, в которой мы начали писать на PHP

Page 54: Автоматизация функционального тестирования REST API

Параметризованные тестыhttps://flamp.ru/api/2.0/filials/?what=кафе&project=1&lon=71&lat=65&radius=1000&sort=relevance&limit=12&page=5&with_markers=false&building_id=1&metarubric=323&depth=1&scopes=reviews&access_token=fa07c31442508e2248fcd634a786d409428ca50d

Page 55: Автоматизация функционального тестирования REST API

Параметризованные тестыhttps://flamp.ru/api/2.0/filials/?what=кафе&project=1&lon=71&lat=65&radius=1000&sort=relevance&limit=12&page=5&with_markers=false&building_id=1&metarubric=323&depth=1&scopes=reviews&access_token=fa07c31442508e2248fcd634a786d409428ca50d

[params_set_1] => 200,[params_set_2] => 404,[params_set_3] => 401,[params_set_4] => 403,[params_set_5] => 400,[params_set_6] => 500,...

Page 56: Автоматизация функционального тестирования REST API

Параметризованные тестыhttps://flamp.ru/api/2.0/filials/?what=кафе&project=1&lon=71&lat=65&radius=1000&sort=relevance&limit=12&page=5&with_markers=false&building_id=1&metarubric=323&depth=1&scopes=reviews&access_token=fa07c31442508e2248fcd634a786d409428ca50d

[params_set_1] => 200,[params_set_2] => 404,[params_set_3] => 401,[params_set_4] => 403,[params_set_5] => 400,[params_set_6] => 500,...

набор N

...

набор 1 тест

Page 57: Автоматизация функционального тестирования REST API

2fingers =PHPUnit + сomposer + http-клиент

(Guzzle поверх cURL) + данные

Page 58: Автоматизация функционального тестирования REST API

данные

dataProvider

параметры

проверки

Структура теста

test

Page 59: Автоматизация функционального тестирования REST API

Тестовые наборыТестовые наборыТестовые наборы

Данные

Установка параметров запроса

источник данных

Проверки

если success

ожидаемый код

ожидаемый результат

фактический результат

ожидаемый кодрольпараметры

запросаобъект

запрос

код ответа

ожидаемый ответ

тело ответа

Page 60: Автоматизация функционального тестирования REST API

Данные

фикстуры дамп

Page 61: Автоматизация функционального тестирования REST API

● реальные

● случайные, но однородные

● уникальные

Требования к данным

Page 62: Автоматизация функционального тестирования REST API

Работа с БД

$entity = Db()->entity('review')->forFilial('141265770608749')

->isHidden(false)->withPhoto(true)->getRandomEntity();

$user_id = Db()->user()->withStatus(1)->getRandomUser()->id;

$article = Db()->table('articles')->isPublished(true)->getRow();

Page 63: Автоматизация функционального тестирования REST API

Всегда ли?

'bacs' => [

'flamp_nsk' => 1,

'flamp_krsk' => 4,

'flamp_msk' => 13,

],

'filials' => [

'pac' => '141265770608749',

'pac2' => '141265771836316',

'bac' => '141265771910841',

'simple' => '141265771459351',

],

config.php

Page 64: Автоматизация функционального тестирования REST API

assertions

$this->assertEquals($user_id, $actual->user_id, “incorrect user_id”);

$this->assertEquals($project_id, $actual->project_id, “incorrect project_id”);

$this->assertEquals($id, $actual->id, “incorrect id”);

...

$this->assert($expected, $actual);

Page 65: Автоматизация функционального тестирования REST API

// Фактический результат$actual = $this->getResponseBody();

// Ожидаемый результат$expected = [

'user' => CHECK_STRING_NOT_EMPTY,'access_token' => CHECK_STRING_NOT_EMPTY

];

// Сравниваем ФР и ОР$this->assert($expected, $actual);

assertions

Page 66: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

Page 67: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

точное значение

точное значение

Page 68: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

точное значение

тип значения и его диапазон

точное значение

Page 69: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

точное значение

enum

тип значения и его диапазон

точное значение

Page 70: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

формат значения

точное значение

enum

тип значения и его диапазон

точное значение

Page 71: Автоматизация функционального тестирования REST API

// Ожидаемый результат $expected = [ 'filial_id' => $filial_id, 'user_id' => $user_id, 'text' => $text, 'date_created' => CHECK_DATETIME_FORMAT, 'date_edited' => null, 'comments_count' => 0, 'likes_score' => 0, 'source' => CHECK_SOURCE, 'filial' => CHECK_NOT_NULL, 'user' => CHECK_EXIST, 'comments' => CHECK_NOT_NULL, 'official_answer' => null, 'additional_data' => [ 'is_liked' => false, 'is_subscribed_to_comments' => false ], 'url' => CHECK_STRING_NOT_EMPTY, 'id' => CHECK_POSITIVE ];

формат значения

точное значение

enum

тип значения и его диапазон

наличие атрибута

точное значение

Page 72: Автоматизация функционального тестирования REST API

Примеры

Page 73: Автоматизация функционального тестирования REST API

public function providerGetBlogAuthors()

{

// запись блога $article = Db()->table('articles')->isPublished(true)->hasAuthor(true)->getRow();

// неопубликованная запись блога $article_not_published = Db()->table('articles')->isPublished(false)->getRow();

return [

// опубликованная [$article, Config()->roles->user, 200],

// неопубликованная под авторизованным юзером [$article_not_published, Config()->roles->user, 404],

// неопубликованная под гостем [$article_not_published, Config()->roles->guest, 404],

];

}

public function testGetBlogAuthors($article, $user_id, $expected_code)

Формируем тестовые наборы

Page 74: Автоматизация функционального тестирования REST API

/**

* @dataProvider providerGetBlogAuthors

*/

public function testGetBlogAuthors($article, $user_id, $expected_code)

{

// Задаём http-метод, метод API, параметры запроса $this->http_method = 'GET';

$this->method = "blogs/{$article->id}/authors";

// Выполняем запрос и проверяем коды ответа $this->asUser($user_id)->send();

$this->waitFor($expected_code);

Получаем авторов записи блога

Page 75: Автоматизация функционального тестирования REST API

// проверяем поля в ответе if ($expected_code === 200) {

$actual = $this->getResponseBody()->authors;

// авторов может быть много, проверяем первого $expected[0] = [

'name' => CHECK_STRING_NOT_EMPTY,

'user' => CHECK_NOT_NULL,

];

$this->assert($expected, $actual);

}

Получаем авторов записи блога

Page 76: Автоматизация функционального тестирования REST API

public function testDeleteReview($entity_id, $cause, $user_id, $expected_code)

{

// Задаём http-метод, метод API, параметры запроса $this->http_method = 'DELETE';

$this->method = "reviews/{$entity_id}";

$this->params = [

'cause' => $cause

];

// Выполняем запрос и проверяем коды ответа $this->asUser($user_id)->send();

$this->waitFor($expected_code);

// Проверка на повторное удаление сущности if ($expected_code === 202) {

$this->asUser($user_id)->send();

$this->waitFor(404);

}

}

Удаляем отзыв

Page 77: Автоматизация функционального тестирования REST API

Запуск и отладка

Page 78: Автоматизация функционального тестирования REST API

Запуск и отладка

Page 79: Автоматизация функционального тестирования REST API

Приёмочное тестирование фичи

10-20 сек

Page 80: Автоматизация функционального тестирования REST API

Регрессия

1400 тестов

35 000 проверок

5 минут 1400 тестов

Page 81: Автоматизация функционального тестирования REST API

Регрессия

1400 тестов

35 000 проверок

5 минут 1400 тестов

28 860 минутвместо

Page 82: Автоматизация функционального тестирования REST API

Процессы

● отдельный репозиторий

● все пушат, мёржат, коммитят

● новая фича покрывается при тестировании,или даже параллельно с разработкой :)

Page 83: Автоматизация функционального тестирования REST API

Flamp API

JSON-schema

Flamposcope

2fingers

Луковица качества API

Page 84: Автоматизация функционального тестирования REST API

Вопросы?