Ответ
При валидации API-ответов я использую многоуровневый подход, который охватывает все аспекты — от HTTP-статусов до бизнес-логики.
Мой стандартный стек для API-тестирования:
- REST Assured (Java) или Supertest (Node.js) для HTTP-запросов
- JSON Schema Validator для проверки структуры
- Hamcrest или AssertJ для читаемых assertions
- Allure для отчетности
Пример комплексной валидации на Java (REST Assured):
@Test
public void getUser_ShouldReturnValidResponse() {
given()
.baseUri("https://api.example.com")
.header("Authorization", "Bearer " + token)
.when()
.get("/users/{id}", 123)
.then()
// 1. Валидация HTTP-уровня
.statusCode(200)
.contentType(ContentType.JSON)
.header("Cache-Control", "max-age=3600")
// 2. Валидация JSON-схемы
.body(matchesJsonSchemaInClasspath("schemas/user-schema.json"))
// 3. Валидация конкретных полей
.body("id", equalTo(123))
.body("name", not(emptyString()))
.body("email", matchesPattern("^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$"))
.body("roles", hasItems("USER", "EDITOR"))
.body("address.city", equalTo("Moscow"))
// 4. Валидация бизнес-правил
.body("createdAt", lessThan("updatedAt"))
.body("isActive", equalTo(true));
}
Для сложных сценариев я добавляю:
Валидацию контрактов (OpenAPI):
// Использую swagger-request-validator
SwaggerValidationFilter validationFilter = new SwaggerValidationFilter("openapi.yaml");
given()
.filter(validationFilter)
// ... остальные параметры
.then()
.assertThat()
.validationPassed(); // Проверка соответствия спецификации
Тестирование граничных случаев:
// Несуществующий пользователь
.when().get("/users/999999")
.then().statusCode(404)
.body("error", equalTo("User not found"));
// Неавторизованный доступ
.when().get("/users/123")
.then().statusCode(401);
// Неверные параметры
.when().get("/users/abc")
.then().statusCode(400);
Валидацию производительности:
.when().get("/users/{id}", 123)
.then().time(lessThan(2000L)); // Ответ менее 2 секунд
Ключевые принципы моей валидации:
- Полнота: Проверяю статус, заголовки, структуру, типы данных, значения
- Изоляция: Каждый тест независим, использую тестовые данные
- Читаемость: Assertions должны явно показывать, что проверяется
- Поддержка: Все схемы и контракты хранятся в репозитории
- Интеграция: Тесты запускаются в CI/CD при каждом изменении API