Урок 07.08: Postman для аналитика — практическая работа с API
Цель урока
Научиться использовать Postman как основной инструмент для тестирования, отладки и документирования API. Пройти полный цикл работы аналитика: от импорта OpenAPI/SOAP-контракта до создания коллекции, настройки окружений, написания скриптов проверки и передачи коллекции в репозиторий. Особый фокус: реальные сценарии аналитика, а не «как нажать кнопку Send».
Ключевые понятия
| Термин | Определение |
|---|---|
| Collection (коллекция) | Группа API-запросов с общей структурой — аналог «папки проекта» |
| Environment (окружение) | Набор переменных (URL, токен, ID), переключаемых между dev/staging/prod |
| Variable (переменная) | {{baseUrl}}, {{token}} — динамические значения, подставляемые в запрос |
| Pre-request Script | JavaScript-скрипт, выполняемый до отправки запроса (например, установка токена) |
| Test Script | JavaScript-скрипт, выполняемый после получения ответа (проверка статуса, тела) |
| Runner | Запуск всей коллекции или её части последовательно |
| Newman | CLI-версия Postman для запуска коллекций в CI/CD (без графического интерфейса) |
| Mock Server | Эмуляция API на основе OpenAPI-спецификации (когда бэкенд ещё не готов) |
| Interceptor / Proxy | Перехват трафика из браузера или мобильного приложения |
| History | История всех отправленных запросов (можно сохранить в коллекцию) |
1. Postman — рабочее место аналитика
1.1. Почему Postman, а не Swagger UI?
| Задача | Swagger UI | Postman |
|---|---|---|
| Быстро «потыкать» API | ✅ Лучше всего (встроенный Try it out) | ⚠️ Нужно импортировать |
| Группировка запросов по сценариям | ❌ Только по эндпоинтам | ✅ Коллекции + папки |
| Переключение между dev/staging/prod | ❌ Только 1 URL из OpenAPI | ✅ Окружения (переменные) |
| Работа с SOAP | ⚠️ Частично (через REST) | ✅ Заголовок SOAPAction + XML Body |
| Pre-request скрипты (авторизация) | ❌ Нет | ✅ JavaScript перед запросом |
| Автоматические тесты | ❌ Нет | ✅ Test Scripts + Chai Assertions |
| Запуск в CI/CD | ❌ Нет | ✅ Newman |
| Mock-сервер | ❌ Нет | ✅ Postman Mock Server |
| Сохранение истории | ⚠️ Временно | ✅ History + сохранение в коллекцию |
| Командная работа | ❌ Нет (одна спецификация) | ✅ Workspaces, Team Collections |
Вывод: Swagger UI — для быстрого ознакомления с API (Try it out). Postman — для систематической работы аналитика: коллекции сценариев, окружения, тесты, передача команде.
1.2. Аналогия: Postman — это «инструментальный ящик» аналитика
REST API — это меню ресторана (что можно заказать)
OpenAPI — это меню с технологическими картами (как готовить)
SOAP WSDL — это контракт с курьерской службой
Postman — это ваш НОЖ и РАЗДЕЛОЧНАЯ ДОСКА:
- Коллекция = набор рецептов (сценариев)
- Окружение = разные кухни (dev, staging, prod)
- Переменные = ингредиенты (token, baseUrl, orderId)
- Тесты = дегустация (проверка, что блюдо съедобно)
1.3. Когда аналитик использует Postman — реальные сценарии
| Сценарий | Что делает аналитик |
|---|---|
| Проверка OpenAPI-контракта | Импортирует OpenAPI → проверяет: все ли эндпоинты работают, правильные ли статус-коды, форматы ответов |
| Тестирование SOAP-интеграции | Настраивает POST + XML Body + SOAPAction → проверяет SOAP Fault |
| Подготовка данных для тестирования | Через API создаёт тестовые сущности (задачи, пользователей) → чтобы тестировщик мог работать с данными |
| Демонстрация заказчику | Показывает: «вот так API работает сейчас. Видите, задача создаётся, возвращается 201» |
| Отладка ошибки интеграции | Копирует неудачный запрос от разработчика → запускает в Postman → анализирует ответ |
| Коллекция для команды | Собирает все эндпоинты в коллекцию, раскладывает по папкам, добавляет описания → экспортирует в Git |
| Проверка безопасности | Пробует: что будет, если не передать токен (401?), неверный токен (403?), SQL-инъекцию |
2. Collections и Environments — база работы
2.1. Структура коллекции (Collection)
Хорошая коллекция аналитика выглядит так:
📁 Task Manager API (коллекция)
│
├── 🏠 Auth
│ ├── POST Register # Регистрация пользователя
│ └── POST Login # Получение JWT-токена
│
├── 📋 Tasks
│ ├── GET All Tasks # Список с фильтрацией
│ ├── GET Task by ID # Получить задачу
│ ├── POST Create Task # Создать задачу
│ ├── PATCH Update Status # Сменить статус
│ └── DELETE Delete Task # Удалить задачу
│
├── 👥 Users
│ ├── GET Profile # Профиль текущего пользователя
│ └── GET All Users # Список пользователей
│
├── 💬 Comments
│ ├── GET Task Comments # Комментарии задачи
│ └── POST Add Comment # Добавить комментарий
│
└── 📊 Reports
└── GET Task Statistics # Статистика по задачам
Правила хорошей коллекции:
| Правило | Пример |
|---|---|
| ✅ Папки по ресурсам | Tasks, Users, Auth |
| ✅ Названия запросов — глагол + сущность | GET All Tasks, POST Create Task |
| ✅ Описание каждого запроса | Что делает, какие параметры |
| ✅ Примеры тел запросов | Pre-filled JSON |
| ✅ Переменные вместо жёстких значений | {{baseUrl}}/tasks/{{taskId}} |
| ✅ Pre-request Script для токена | Автоматически устанавливает {{token}} |
| ✅ Test Scripts для проверок | Проверяет статус, тип ответа |
2.2. Окружения (Environments)
Окружение — это набор переменных, которые подставляются в коллекцию.
Пример окружения «Development»:
{
"baseUrl": "http://localhost:8080/api/v1",
"token": "",
"taskId": "",
"userId": "",
"limit": 10
}
Пример окружения «Staging»:
{
"baseUrl": "https://staging-api.taskmanager.com/api/v1",
"token": "",
"taskId": "",
"userId": "",
"limit": 20
}
Пример окружения «Production»:
{
"baseUrl": "https://api.taskmanager.com/api/v1",
"token": "",
"taskId": "",
"userId": "",
"limit": 50
}
Как работает подстановка:
Запрос в коллекции: GET {{baseUrl}}/tasks/{{taskId}}?limit={{limit}}
Окружение Dev: baseUrl = http://localhost:8080/api/v1, taskId = 42, limit = 10
Реальный URL: GET http://localhost:8080/api/v1/tasks/42?limit=10
Типы переменных в Postman:
| Область видимости | Приоритет | Когда использовать |
|---|---|---|
| Global | 4 (низший) | Статические значения, общие для всех коллекций (например, apiVersion) |
| Environment | 3 | Разные для dev/staging/prod (например, baseUrl) |
| Collection | 2 | Общие для одной коллекции (например, baseUrl, если коллекция самодостаточна) |
| Data | 1 | Из CSV/JSON при запуске Runner (для тестовых данных) |
| Local | 5 (высший) | Внутри одного запроса/скрипта (через pm.variables.set()) |
2.3. Pre-request Script: автоматическая авторизация
Самый частый сценарий: перед каждым запросом нужно установить JWT-токен.
Pre-request Script для коллекции (Collection → Pre-request Script):
// Если токен в окружении пуст или истекает — выполнить login
const token = pm.environment.get("token");
if (!token || token === "") {
console.log("Token not found — executing login...");
pm.sendRequest({
url: pm.environment.get("baseUrl") + "/auth/login",
method: "POST",
header: {
"Content-Type": "application/json"
},
body: {
mode: "raw",
raw: JSON.stringify({
email: pm.environment.get("testUserEmail"),
password: pm.environment.get("testUserPassword")
})
}
}, function (err, response) {
if (!err) {
const newToken = response.json().token;
pm.environment.set("token", newToken);
console.log("Token obtained:", newToken);
} else {
console.error("Login failed:", err);
}
});
}
Что это даёт:
- При запуске любого запроса из коллекции токен проверяется
- Если токена нет — автоматически выполняется
POST /auth/login - Полученный токен сохраняется в переменную
{{token}} - Все запросы используют
Authorization: Bearer {{token}}
2.4. Collection Variables — «секреты» коллекции
Переменные коллекции удобны для значений, которые не должны меняться между окружениями:
📋 Collection Variables:
┌─────────────────────┬──────────────────────────────────┐
│ Variable │ Initial Value │
├─────────────────────┼──────────────────────────────────┤
│ appName │ Task Manager API │
│ apiVersion │ v1 │
│ supportedStatuses │ To Do,In Progress,Testing,Done │
│ schemaVersion │ 1.2.0 │
└─────────────────────┴──────────────────────────────────┘
3. Импорт OpenAPI-спецификации
3.1. Как импортировать
У аналитика есть OpenAPI-спецификация (YAML/JSON). Нужно получить коллекцию Postman.
Postman → Import → File (выбрать .yaml/.json)
→ Import → Link (указать URL спецификации)
→ Import → Raw Text (вставить содержимое)
Что Postman делает автоматически:
| Исходный OpenAPI | Результат в Postman |
|---|---|
openapi: 3.1.0 |
Определяет версию |
servers: |
Создаёт переменную окружения baseUrl |
paths: /tasks |
Папка в коллекции «Tasks» |
paths: /tasks get |
Запрос «GET All Tasks» |
paths: /tasks/{taskId} |
Запрос «GET Task by ID» (с path-параметром) |
components/schemas |
(не импортируются напрямую, но используются в примерах) |
securitySchemes BearerAuth |
Настраивает Authorization: Bearer {{token}} |
3.2. Что проверить после импорта (чек-лист аналитика)
| № | Проверка | Если проблема | Решение |
|---|---|---|---|
| 1 | Переменная baseUrl создалась? |
Нет в окружении | Создать вручную из servers |
| 2 | Все эндпоинты импортировались? | Пропущен эндпоинт | Проверить OpenAPI на ошибки |
| 3 | Path-параметры (:taskId) корректны? |
Параметр не подставился | Ручное исправление: :id → {{id}} |
| 4 | Query-параметры отобразились? | Нет в Params | Добавить вручную |
| 5 | Примеры тел запросов заполнены? | Пустое тело | Взять из example в OpenAPI |
| 6 | Аутентификация настроена? | Нет заголовка | Добавить Authorization: Bearer {{token}} |
| 7 | Описания (description) эндпоинтов видны? | Нет | Скопировать из OpenAPI вручную |
3.3. Пример: импорт из OpenAPI → что получилось
OpenAPI (фрагмент):
paths:
/tasks/{taskId}:
get:
operationId: getTaskById
summary: "Получить задачу по ID"
parameters:
- name: taskId
in: path
required: true
schema:
type: integer
- name: include
in: query
schema:
type: string
responses:
"200":
description: "Задача найдена"
content:
application/json:
schema:
$ref: "#/components/schemas/Task"
"404":
description: "Задача не найдена"
После импорта в Postman:
📁 Tasks
└── 🔹 GET Task by ID
└── Method: GET
└── URL: {{baseUrl}}/tasks/{{taskId}}
└── Params:
└── Path: taskId → {{taskId}} (required)
└── Query: include → (optional)
└── Headers:
└── Authorization: Bearer {{token}}
└── Pre-request Script: (автологин, если токен пуст)
└── Test Scripts:
└── Status 200 for success
└── Status 404 for not found
└── Response time < 2000ms
4. Ручное тестирование REST API
4.1. Настройка запроса: пошагово
┌──────────────────────────────────────────────────────────────┐
│ POST {{baseUrl}}/tasks [Send] │
├──────────────────────────────────────────────────────────────┤
│ Params │ Authorization │ Headers (8) │ Body │ Scripts │ ... │
├──────────────────────────────────────────────────────────────┤
│ Body: raw (JSON) │
│ │
│ { │
│ "title": "Настроить CI/CD", │
│ "description": "GitHub Actions pipeline", │
│ "priority": "High", │
│ "projectId": 1, │
│ "assigneeId": 42, │
│ "deadline": "2026-07-15" │
│ } │
├──────────────────────────────────────────────────────────────┤
│ Response: 201 Created (1.2 сек) │
├──────────────────────────────────────────────────────────────┤
│ { │
│ "id": 128, │
│ "title": "Настроить CI/CD", │
│ "status": "To Do", │
│ "createdAt": "2026-06-12T10:30:00Z" │
│ } │
├──────────────────────────────────────────────────────────────┤
│ Tests (1/1) ✓ Status code is 201 │
└──────────────────────────────────────────────────────────────┘
Вкладки запроса — что делает аналитик:
| Вкладка | Что настраивает | Типичные действия |
|---|---|---|
| Params | Path- и Query-параметры | Устанавливает {{taskId}}, ?status=Done&page=1 |
| Authorization | Тип аутентификации | Bearer Token → {{token}} |
| Headers | Дополнительные заголовки | Content-Type: application/json, X-Request-Id: {{$guid}} |
| Body | Тело запроса | JSON, XML (SOAP), form-data, binary |
| Pre-request | Скрипт до запроса | Автологин, генерация timestamp |
| Tests | Скрипт после ответа | Проверка статуса, тела, времени |
4.2. Частая ошибка: Postman «сам» не подставляет пути
URL: {{baseUrl}}/tasks/{{taskId}}
❌ Если переменная taskId не задана — URL станет:
http://localhost:8080/api/v1/tasks/
→ 404 Not Found (нет ID)
✅ Как настроить:
1. Задать taskId в окружении: 42
2. Или в Params → Path Variables → taskId = 42
3. Или через Pre-request Script: pm.environment.set("taskId", "42")
4.3. Collection Runner — прогон всех сценариев
После того как вы собрали коллекцию, можно запустить Runner:
Postman → Runner → Выбрать коллекцию
→ Выбрать окружение
→ Run Order (порядок запросов)
→ Iterations (сколько раз прогнать)
→ Delay (задержка между запросами)
→ Data (CSV/JSON-файл с тестовыми данными)
→ [Run TaskManager API]
Результат прогона:
┌──────────────────────────────────────────────────────────────┐
│ Run Results: Task Manager API (7 requests, 3 iterations) │
│ │
│ ✅ POST Auth / Login → 200 OK (3/3 passed) │
│ ✅ POST Tasks / Create Task → 201 OK (3/3 passed) │
│ ✅ GET Tasks / All Tasks → 200 OK (3/3 passed) │
│ ✅ GET Tasks / Task by ID → 200 OK (3/3 passed) │
│ ✅ PATCH Tasks / Update Status → 200 OK (3/3 passed) │
│ ✅ GET Tasks / Task Comments → 200 OK (3/3 passed) │
│ ✅ DELETE Tasks / Delete Task → 204 OK (3/3 passed) │
│ │
│ Total: 21/21 passed, 0 failed │
│ Average response time: 245ms │
└──────────────────────────────────────────────────────────────┘
Что даёт аналитику:
- Проверка, что все эндпоинты работают
- Что сценарии проходят последовательно (создали → прочитали → обновили → удалили)
- Что нет регрессии после изменений бэкенда
- Можно экспортировать отчёт (HTML/JSON)
5. SOAP в Postman
Postman поддерживает SOAP, но с ограничениями (по сравнению с SoapUI).
5.1. Настройка SOAP-запроса
┌──────────────────────────────────────────────────────────────┐
│ POST https://api.example.com/soap/taskmanager/v1 [Send] │
├──────────────────────────────────────────────────────────────┤
│ Body: raw → XML │
│ │
│ <?xml version="1.0" encoding="UTF-8"?> │
│ <soap:Envelope │
│ xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" │
│ xmlns:task="http://www.example.com/taskmanager"> │
│ │
│ <soap:Header/> │
│ │
│ <soap:Body> │
│ <task:CreateTask> │
│ <task:title>Test task from Postman</task:title> │
│ <task:projectId>1</task:projectId> │
│ </task:CreateTask> │
│ </soap:Body> │
│ </soap:Envelope> │
├──────────────────────────────────────────────────────────────┤
│ Headers: │
│ Content-Type: text/xml; charset=utf-8 (SOAP 1.1) │
│ SOAPAction: "http://www.example.com/taskmanager/CreateTask"│
│ (или Content-Type: application/soap+xml для SOAP 1.2) │
└──────────────────────────────────────────────────────────────┘
5.2. Postman vs SoapUI для SOAP
| Возможность | Postman | SoapUI |
|---|---|---|
| Импорт WSDL | ❌ Не умеет | ✅ Авто-генерация запросов |
| Формирование Envelope | ❌ Ручной XML | ✅ Автоматическое |
| Namespace-менеджмент | ❌ Ручной | ✅ Автоматический |
| SOAP Action | ✅ Ручной заголовок | ✅ Автоматический |
| WS-Security | ❌ Нет поддержки | ✅ Настройка UsernameToken |
| Проверка XPath | ⚠️ Через Test Scripts | ✅ Встроенные Assertions |
| Mock SOAP Server | ❌ Нет | ✅ Да |
| Load Testing | ❌ Ограничен | ✅ Встроенный |
Вывод для аналитика:
- Если есть WSDL и нужна серьёзная работа с SOAP → SoapUI
- Если нужно быстро «пощупать» SOAP-запрос или один раз проверить → Postman
- Постман не заменяет SoapUI для SOAP, но удобен, когда SOAP — малая часть работы
5.3. Pre-request Script для WS-Security (UsernameToken)
Если SOAP-сервис требует WS-Security, можно сгенерировать UsernameToken в Pre-request Script:
// Pre-request Script: генерация WS-Security UsernameToken
const username = pm.environment.get("soapUsername");
const password = pm.environment.get("soapPassword");
const nonce = CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Base64);
const created = new Date().toISOString().replace(/\.\d{3}/, '');
const passwordDigest = CryptoJS.SHA256(nonce + created + password)
.toString(CryptoJS.enc.Base64);
pm.environment.set("wsseUsername", username);
pm.environment.set("wssePasswordDigest", passwordDigest);
pm.environment.set("wsseNonce", nonce);
pm.environment.set("wsseCreated", created);
6. Test Scripts — автоматическая проверка ответа
6.1. Стандартный набор проверок для аналитика
Postman использует библиотеку Chai (BDD-стиль) с pm.expect().
Шаблон Tests для любого запроса:
// 1. Статус-код
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// 2. Время ответа
pm.test("Response time < 2000 ms", function () {
pm.expect(pm.response.responseTime).to.be.below(2000);
});
// 3. Content-Type
pm.test("Content-Type is JSON", function () {
pm.response.to.have.header("Content-Type", "application/json; charset=utf-8");
});
// 4. Тело ответа не пустое
pm.test("Response body is not empty", function () {
pm.response.to.have.body();
});
6.2. Проверки для конкретных эндпоинтов
POST Create Task (должен вернуть 201 + Task):
pm.test("Status 201 Created", () => pm.response.to.have.status(201));
const jsonData = pm.response.json();
pm.test("Task has required fields", () => {
pm.expect(jsonData).to.have.property("id");
pm.expect(jsonData).to.have.property("title");
pm.expect(jsonData).to.have.property("status");
pm.expect(jsonData).to.have.property("createdAt");
});
pm.test("Status is 'To Do'", () => {
pm.expect(jsonData.status).to.eql("To Do");
});
pm.test("ID is integer", () => {
pm.expect(jsonData.id).to.be.a("number");
});
// Сохраняем ID для следующих запросов
pm.environment.set("taskId", jsonData.id);
GET Task by ID (должен вернуть 200 + ту же задачу):
pm.test("Status 200 OK", () => pm.response.to.have.status(200));
const jsonData = pm.response.json();
pm.test("Task matches expected ID", () => {
pm.expect(jsonData.id).to.eql(parseInt(pm.environment.get("taskId")));
});
pm.test("Response matches schema", () => {
const schema = {
type: "object",
required: ["id", "title", "status", "createdAt"],
properties: {
id: { type: "number" },
title: { type: "string" },
status: { type: "string", enum: ["To Do", "In Progress", "Testing", "Done", "Blocked"] },
createdAt: { type: "string" }
}
};
pm.response.to.have.jsonSchema(schema);
});
PATCH Update Status (проверка идемпотентности):
pm.test("Status 200 OK", () => pm.response.to.have.status(200));
const jsonData = pm.response.json();
pm.test("Status changed to 'In Progress'", () => {
pm.expect(jsonData.status).to.eql("In Progress");
});
// Проверка: второй PATCH с тем же статусом не меняет updatedAt (идемпотентность)
pm.test("Idempotency: same status does not change updatedAt", () => {
const previousUpdatedAt = pm.environment.get("taskUpdatedAt");
if (previousUpdatedAt) {
// Если уже обновляли — проверить, что updatedAt не изменился
pm.expect(jsonData.updatedAt).to.eql(previousUpdatedAt);
} else {
// Первый раз — сохраняем
pm.environment.set("taskUpdatedAt", jsonData.updatedAt);
}
});
DELETE Delete Task (должен вернуть 204 No Content):
pm.test("Status 204 No Content", () => pm.response.to.have.status(204));
pm.test("Response body is empty", () => {
pm.expect(pm.response.body).to.be.empty;
});
// Проверка: повторный DELETE возвращает 404
pm.test("Second delete returns 404 (idempotency)", () => {
// Эта проверка запускается ДО первой отправки, поэтому делаем 2 запроса
pm.sendRequest({
url: pm.environment.get("baseUrl") + "/tasks/" + pm.environment.get("taskId"),
method: "DELETE",
header: { "Authorization": "Bearer " + pm.environment.get("token") }
}, function (err, response) {
pm.expect(response.code).to.eql(404);
});
});
6.3. Проверка SOAP-ответа
pm.test("SOAP Fault not present", () => {
// Если в ответе есть SOAP Fault — тест не пройден
const hasFault = pm.response.text().includes("<soap:Fault>") ||
pm.response.text().includes("<soap12:Fault>");
pm.expect(hasFault).to.be.false;
});
pm.test("Response has CreateTaskResponse", () => {
pm.expect(pm.response.text()).to.include("CreateTaskResponse");
});
// Извлечение taskId из XML через регулярное выражение
pm.test("Task ID extracted from SOAP response", () => {
const match = pm.response.text().match(/<task:taskId>(\d+)<\/task:taskId>/);
if (match && match[1]) {
pm.environment.set("taskId", parseInt(match[1]));
}
pm.expect(match).to.not.be.null;
});
6.4. Чек-лист тестов для каждого эндпоинта
| Эндпоинт | Проверки |
|---|---|
| GET /tasks | 200, тело — массив, пагинация {data, pagination}, каждый объект — Task |
| GET /tasks/{id} | 200 (есть), 404 (нет), тело — Task, поля соответствуют схеме |
| POST /tasks | 201, тело — Task с id, status = "To Do", обязательные поля |
| POST /tasks (invalid) | 422, тело — ErrorResponse с code + message |
| PATCH /tasks/{id}/status | 200, статус изменился, идемпотентность |
| DELETE /tasks/{id} | 204 (первый), 404 (второй), тело пустое |
| POST /auth/login | 200, тело — {token, user}, token — непустая строка |
| POST /auth/login (bad pass) | 401, тело — ErrorResponse |
| GET /tasks (no auth) | 401, тело — ErrorResponse |
7. Newman — запуск коллекций в CI/CD
7.1. Что такое Newman
Newman — это консольная (CLI) версия Postman. Она позволяет запускать коллекции:
- В CI/CD (GitLab CI, Jenkins, GitHub Actions)
- На сервере (Linux без GUI)
- В автоматических тестах ночью (nightly build)
7.2. Установка и запуск
# Установка (требуется Node.js)
npm install -g newman
# Запуск коллекции
newman run "Task Manager API.postman_collection.json" \
--environment "Staging.postman_environment.json" \
--reporters cli,htmlextra \
--reporter-htmlextra-export ./reports/api-test-report.html
7.3. Что видит аналитик в отчёте Newman
Newman генерирует HTML-отчёт с результатами:
┌─────────────────────────────────────────────────────────────┐
│ Newman Report — Task Manager API │
│ Environment: Staging │
│ Date: 2026-06-12T10:30:00Z │
│ │
│ ┌───────┬────────────────────────────────┬────────┬───────┐│
│ │ Status│ Request │ Time │ Test ││
│ ├───────┼────────────────────────────────┼────────┼───────┤│
│ │ ✅ │ POST Auth / Login │ 450ms │ 3/3 ││
│ │ ✅ │ POST Tasks / Create Task │ 320ms │ 4/4 ││
│ │ ✅ │ GET Tasks / All Tasks │ 210ms │ 3/3 ││
│ │ ✅ │ GET Tasks / Task by ID │ 180ms │ 3/3 ││
│ │ ✅ │ PATCH Tasks / Update Status │ 250ms │ 4/4 ││
│ │ ✅ │ DELETE Tasks / Delete Task │ 100ms │ 3/3 ││
│ ├───────┼────────────────────────────────┼────────┼───────┤│
│ │ │ Total: 6/6 passed, 0 failed │ 1.5s │ 20/20 ││
│ └───────┴────────────────────────────────┴────────┴───────┘│
│ │
│ Failed tests: — │
│ Warnings: │
│ • PATCH Tasks / Update Status: avg time 450ms > 300ms │
└─────────────────────────────────────────────────────────────┘
7.4. Пример интеграции в CI/CD (GitHub Actions)
name: API Tests
on:
pull_request:
paths:
- 'backend/**'
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start backend
run: docker-compose up -d backend
- name: Install Newman
run: npm install -g newman newman-reporter-htmlextra
- name: Run API tests
run: |
newman run collections/task-manager-api.json \
--environment collections/staging-env.json \
--reporters cli,htmlextra \
--reporter-htmlextra-export reports/api-test-report.html
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: api-test-report
path: reports/api-test-report.html
8. Mock Server — API без бэкенда
8.1. Когда это нужно аналитику
| Сценарий | Без Mock Server | С Mock Server |
|---|---|---|
| Фронтенд готов, бэкенд — нет | Фронтенд ждёт | Фронтенд работает против Mock |
| Нужно показать API заказчику | «Вот OpenAPI, читайте» | «Вот интерактивный прототип, нажимайте кнопки» |
| Зависимый сервис ещё не готов | Интеграция заблокирована | Можно тестировать изолированно |
| Нужны тестовые сценарии (ошибки) | Трудно воспроизвести | Mock возвращает нужную ошибку по требованию |
8.2. Как создать Mock Server в Postman
# Способ 1: Из коллекции
# Postman → Collection → ... → Mock Server → Create New Mock Server
# Postman создаёт URL: https://xxxx.mock.pstmn.io
# Способ 2: Из OpenAPI (без Postman-коллекции)
# Postman → New → Mock Server → Upload OpenAPI → Create
Примеры ответов Mock Server:
// Запрос: GET {{mockUrl}}/tasks/42
// Ответ (на основе example из OpenAPI или сохранённого примера в коллекции):
{
"id": 42,
"title": "Mock Task",
"status": "To Do",
"priority": "Medium",
"createdAt": "2026-06-12T10:00:00Z"
}
// Запрос: GET {{mockUrl}}/tasks/999
// Ответ (на основе сохранённого примера 404):
{
"error": {
"code": "NOT_FOUND",
"message": "Task with id 999 not found"
}
}
8.3. Примеры (Response Examples) — ключ к Mock Server
Чтобы Mock Server возвращал разные ответы на разные запросы, нужно сохранить Example Responses в коллекции:
📁 Tasks
└── 🔹 GET Task by ID
├── 📝 Example: Success (200) ← ответ для существующей задачи
│ { "id": 42, "title": "...", "status": "To Do" }
└── 📝 Example: Not Found (404) ← ответ для несуществующей задачи
{ "error": { "code": "NOT_FOUND", ... } }
Postman Mock Server анализирует:
- Method (GET/POST/...)
- URL path (/tasks/42 vs /tasks/999)
- Query params (?status=done)
- Request body (для POST/PATCH/PUT)
- Выбирает подходящий Example
9. Пример рабочего процесса аналитика в Postman
9.1. Полный цикл: от контракта до коллекции в Git
┌────────────────────────────────────────────────────────────────┐
│ ЭТАП 1: ПОЛУЧЕНИЕ КОНТРАКТА │
│ │
│ Разработчик или партнёр передаёт: │
│ • OpenAPI YAML (для REST) или URL WSDL (для SOAP) │
│ • Или: черновик на бумаге │
│ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ ЭТАП 2: СОЗДАНИЕ КОЛЛЕКЦИИ │
│ │
│ Действия аналитика: │
│ 1. Postman → Import → OpenAPI файл │
│ 2. Проверить: все ли эндпоинты импортированы │
│ 3. Разложить по папкам (Auth, Tasks, Users, Comments) │
│ 4. Добавить описания (description) к запросам │
│ 5. Создать окружения (Dev, Staging, Prod) │
│ 6. Настроить Pre-request Script (автологин, токен) │
│ 7. Написать Test Scripts для каждого эндпоинта │
│ 8. Сохранить примеры ответов (Example Responses) │
│ 9. Экспортировать коллекцию и окружение в JSON │
│ 10. Закоммитить в репозиторий (например, в /collections/) │
│ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ ЭТАП 3: ТЕСТИРОВАНИЕ │
│ │
│ 1. Ручной прогон ключевых сценариев (Positive + Negative) │
│ 2. Runner: прогон всей коллекции (3-5 итераций) │
│ 3. Если нашли баг: │
│ • Зафиксировать запрос (Save Response) │
│ • Приложить к баг-репорту (Export → Share) │
│ 4. Исправления в контракте → обновить OpenAPI → переимпорт │
│ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ ЭТАП 4: ПЕРЕДАЧА КОМАНДЕ │
│ │
│ Кому: │
│ • Тестировщикам (они используют коллекцию для тест-кейсов) │
│ • Фронтенд-разработчикам (проверяют формат ответов) │
│ • Бэкенд-разработчикам (видят ожидаемое поведение) │
│ │
│ Формат: │
│ • JSON-файлы коллекции + окружения в Git │
│ • Ссылка на Postman Workspace (Team) │
│ • Newman-команда для CI/CD │
│ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ ЭТАП 5: ПОДДЕРЖКА (при изменениях API) │
│ │
│ 1. Разработчик меняет API → обновляет OpenAPI │
│ 2. Аналитик: Postman → Import (Update existing) │
│ 3. Проверить: какие эндпоинты изменились │
│ 4. Обновить Test Scripts под новое поведение │
│ 5. Прогнать Runner → убедиться, что регрессии нет │
│ 6. Закоммитить обновлённую коллекцию │
│ │
└────────────────────────────────────────────────────────────────┘
9.2. Что экспортировать в Git
📁 collections/
├── Task Manager API.postman_collection.json # Коллекция
├── Dev.postman_environment.json # Окружение Dev
├── Staging.postman_environment.json # Окружение Staging
└── Production.postman_environment.json # Окружение Prod (без sensitive-данных!)
Важно: Не коммитить токены и пароли в Git. Используйте initial значения, а current — через CI/CD переменные или .env:
{
"key": "token",
"value": "",
"type": "secret",
"enabled": true
}
9.3. Полезные динамические переменные Postman
| Переменная | Значение | Пример использования |
|---|---|---|
{{$guid}} |
Случайный UUID | Идемпотентность: Idempotency-Key: {{$guid}} |
{{$timestamp}} |
Unix timestamp в секундах | ?since={{$timestamp}} |
{{$isoTimestamp}} |
ISO 8601 дата-время | Поле createdAt в теле запроса |
{{$randomEmail}} |
Случайный email | Регистрация тестового пользователя |
{{$randomInt}} |
Случайное целое | ID несуществующего ресурса |
{{$randomUUID}} |
UUID (версия 4) | Correlation ID |
Пример регистрации нового пользователя с динамическим email:
{
"name": "Test User",
"email": "{{$randomEmail}}",
"password": "TestPass123!"
}
Каждый запуск Postman подставит новый email → не будет конфликта дубликатов.
10. Postman Workspaces — командная работа
10.1. Типы Workspaces
| Тип | Для кого | Особенность |
|---|---|---|
| Personal | Вы один | Личные эксперименты |
| Team | Вся команда | Коллекции, окружения, история — общие |
| Private | Только приглашённые | Для заказчика или партнёра (ограниченный доступ) |
| Public | Все | Публичные API (можно ссылаться в документации) |
10.2. Что даёт Team Workspace
- Единая коллекция — все видят актуальные запросы
- Не нужно пересылать JSON-файлы
- История изменений (кто, что, когда изменил)
- Комментарии к запросам
- Activity log
Вопросы для самопроверки
Базовый уровень
- Чем Postman отличается от Swagger UI? В каких сценариях каждый удобнее?
- Что такое Collection, Environment, Variable в Postman? Как они связаны?
- Как импортировать OpenAPI-спецификацию в Postman? Что нужно проверить после импорта?
- Зачем аналитику писать Test Scripts в Postman? Приведите 3 примера проверок.
- Что такое Newman и зачем он нужен в CI/CD?
Продвинутый уровень
- Chain запросов: У вас в коллекции 3 запроса: Login → Create Task → Get Task by ID. Как передать
taskIdиз второго запроса в третий? - SOAP vs REST в Postman: Какие ограничения Postman для SOAP? В каком случае вы выберете SoapUI вместо Postman?
- Mock Server: Заказчик хочет увидеть, как будет работать API через 2 недели (бэкенд ещё не готов). Что вы сделаете?
- Pre-request Script: Напишите скрипт, который перед каждым запросом проверяет, не истёк ли JWT-токен, и если истёк — выполняет автоматический login.
- Командная работа: Как организовать работу с Postman в команде из 10 человек так, чтобы коллекция всегда была актуальной, а токены и пароли не попадали в Git?
Практическое задание
Задание 1. Создание окружений (2 балла)
Создайте три окружения Postman для Task Manager API:
| Окружение | baseUrl | limit | Аутентификация |
|---|---|---|---|
| Development | http://localhost:8080/api/v1 |
10 | test@example.com / TestPass123 |
| Staging | https://staging-api.taskmanager.com/api/v1 |
25 | test@example.com / TestPass123 |
| Production | https://api.taskmanager.com/api/v1 |
50 | — (токен не хранить) |
1.1. (1 балл) Опишите в Markdown-таблице, какие переменные в каждом окружении и их значения. 1.2. (1 балл) Объясните, почему токен не должен храниться в Production-окружении. Как правильно организовать аутентификацию в Production?
Задание 2. OpenAPI → Коллекция (3 балла)
Возьмите OpenAPI-спецификацию из урока 07.02 (или любую существующую OpenAPI 3.x для системы задач).
2.1. (1 балл) Импортируйте её в Postman. Перечислите, что импортировалось корректно, а что пришлось донастроить вручную.
2.2. (1 балл) Разложите запросы по папкам (Auth, Tasks, Users, Comments). Добавьте описание к каждой папке.
2.3. (1 балл) Настройте Pre-request Script для автоматической авторизации (если нет токена — выполнить POST /auth/login).
Задание 3. Test Scripts (3 балла)
Напишите Test Scripts для трёх эндпоинтов:
3.1. POST /tasks (Create Task) — проверки:
- Статус-код 201
- Content-Type: application/json
- Тело содержит id (integer), title, status="To Do", createdAt (date-time)
- Сохранить taskId в переменную окружения
3.2. GET /tasks/{taskId} (Get Task) — проверки:
- Статус-код 200
- Тело соответствует схеме Task
- id совпадает с taskId из окружения
- Время ответа < 1500ms
3.3. DELETE /tasks/{taskId} (Delete Task) — проверки:
- Статус-код 204
- Тело пустое
- Повторный DELETE возвращает 404
Задание 4. Newman — CI/CD (1 балл)
Напишите команду Newman для запуска коллекции Task Manager API:
- Файл коллекции:
collections/task-manager-api.json - Окружение:
collections/staging-env.json - Формат отчёта: cli + htmlextra
- Путь для отчёта:
./reports/api-test-report.html - Задержка между запросами: 500ms
Задание 5. Рабочий процесс аналитика (1 балл)
К вам пришёл разработчик и сказал: «Я изменил API — добавил новый эндпоинт PATCH /tasks/{taskId}/assign (назначить исполнителя) и удалил поле description из ответа GET /tasks/{taskId}».
Опишите пошагово, что вы сделаете как аналитик в Postman:
- Как узнаете об изменениях?
- Как обновите коллекцию?
- Как проверите, что старые сценарии не сломались?
- Как передадите коллекцию тестировщикам?
Критерии оценки
| Задание | Баллы |
|---|---|
| Задание 1: Создание окружений | 2 |
| Задание 2: OpenAPI → Коллекция | 3 |
| Задание 3: Test Scripts | 3 |
| Задание 4: Newman — CI/CD | 1 |
| Задание 5: Рабочий процесс аналитика | 1 |
| Итого | 10 |
Справочные материалы
Динамические переменные Postman
| Переменная | Формат | Пример |
|---|---|---|
{{$guid}} |
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX |
3f5c8e1a-2b4d-4a7f-9c6e-1d2b3c4d5e6f |
{{$timestamp}} |
Unix epoch seconds | 1718171400 |
{{$isoTimestamp}} |
ISO 8601 | 2026-06-12T10:30:00.000Z |
{{$randomEmail}} |
user42@example.com |
|
{{$randomInt}} |
0–1000 | 847 |
{{$randomUUID}} |
UUID v4 | c4e1f3a8-7b2d-4e6f-9a1c-3d5b7e8f2a0c |
Полезные сниппеты Test Scripts
// Проверка статуса
pm.test("Status is 200", () => pm.response.to.have.status(200));
// Проверка заголовка
pm.test("Content-Type is JSON", () => {
pm.response.to.have.header("Content-Type", "application/json");
});
// Проверка тела (свойство существует)
pm.test("Body has id", () => {
pm.expect(pm.response.json()).to.have.property("id");
});
// Проверка типа поля
pm.test("id is number", () => {
pm.expect(pm.response.json().id).to.be.a("number");
});
// Проверка массива
pm.test("Response is array of tasks", () => {
const tasks = pm.response.json().data;
pm.expect(tasks).to.be.an("array");
pm.expect(tasks.length).to.be.at.least(1);
tasks.forEach(task => {
pm.expect(task).to.have.property("id");
pm.expect(task).to.have.property("title");
});
});
// Проверка JSON Schema
pm.test("Response matches schema", () => {
const schema = { type: "object", required: ["id", "title", "status"] };
pm.response.to.have.jsonSchema(schema);
});
// Сохранение значения из ответа
const id = pm.response.json().id;
pm.environment.set("taskId", id);
Быстрые ссылки
| Ресурс | URL |
|---|---|
| Postman Download | https://www.postman.com/downloads/ |
| Newman CLI | https://github.com/postmanlabs/newman |
| Postman Mock Servers | https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/ |
| Postman Sandbox API | https://learning.postman.com/docs/writing-scripts/script-references/postman-sandbox-api-reference/ |
| Newman HTML Reporter | https://github.com/postmanlabs/newman-reporter-htmlextra |
| Postman Collection Format | https://schema.postman.com/ |