package ru.otus.petstore; import io.restassured.RestAssured; import io.restassured.http.ContentType; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.TestWatcher; import org.junit.jupiter.api.extension.ExtensionContext; import java.util.Optional; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.*; @ExtendWith(PetStoreTests.TestResultLogger.class) @TestMethodOrder(OrderAnnotation.class) public class PetStoreTests { /** * Выполняется один раз перед запуском всех тестов. * Устанавливаем базовый URI для запросов к Swagger Petstore API. */ @BeforeAll public static void setup() { RestAssured.baseURI = "https://petstore.swagger.io/v2"; } /** * Тест 1: GET /pet/findByStatus (status = available). * Ожидается статус 200 и все объекты в ответе должны иметь поле "status" равное "available". */ @Test @Order(1) @DisplayName("1. Test: Find pets by 'available' status") public void testFindPetsByAvailableStatus() { given() .queryParam("status", "available") .when() .get("/pet/findByStatus") .then() .statusCode(200) .body("status", everyItem(equalTo("available"))); } /** * Тест 2: GET /pet/findByStatus с несуществующим статусом "invalidStatus". * Ожидается статус 200 и пустой массив в ответе. */ @Test @Order(2) @DisplayName("2. Test: Find pets by invalid status") public void testFindPetsByInvalidStatus() { given() .queryParam("status", "invalidStatus") .when() .get("/pet/findByStatus") .then() .statusCode(200) .body("", hasSize(0)); } /** * Тест 3: POST /pet для создания питомца с валидными данными. * Ожидается статус 200 и возвращаемое поле "name" совпадает с переданным. */ @Test @Order(3) @DisplayName("3. Test: Create pet successfully") public void testCreatePetSuccess() { int petId = (int) (System.currentTimeMillis() % Integer.MAX_VALUE); String petName = "Rex"; String requestBody = "{\n" + " \"id\": " + petId + ",\n" + " \"category\": { \"id\": 1, \"name\": \"Dogs\" },\n" + " \"name\": \"" + petName + "\",\n" + " \"photoUrls\": [ \"http://example.com/photo.jpg\" ],\n" + " \"tags\": [ { \"id\": 0, \"name\": \"string\" } ],\n" + " \"status\": \"available\"\n" + "}"; given() .contentType(ContentType.JSON) .body(requestBody) .when() .post("/pet") .then() .statusCode(200) .body("name", equalTo(petName)); } /** * Тест 4: POST /pet для создания питомца с невалидными данными (без поля "name"). * Ожидается, что API вернёт ошибку (400 или 405). Почему-то сервис отдает ответ 200 * я решил оставить данный тест. Показать что вся цепочка тестов не останавливается и * продолжает работать дальше */ @Test @Order(4) @DisplayName("4. Test: Fail to create pet without 'name' field") public void testCreatePetMissingName() { int petId = (int) (System.currentTimeMillis() % Integer.MAX_VALUE); String requestBody = "{\n" + " \"id\": " + petId + ",\n" + " \"category\": { \"id\": 1, \"name\": \"Dogs\" },\n" + " \"photoUrls\": [ \"http://example.com/photo.jpg\" ],\n" + " \"tags\": [ { \"id\": 0, \"name\": \"string\" } ],\n" + " \"status\": \"available\"\n" + "}"; given() .contentType(ContentType.JSON) .body(requestBody) .when() .post("/pet") .then() .statusCode(anyOf(is(400), is(405))); } /** * Тест 5: POST /pet с некорректным JSON (отсутствует закрывающая фигурная скобка). * Ожидается, что API вернёт ошибку (400 или 405). */ @Test @Order(5) @DisplayName("5. Test: Create pet with invalid JSON") public void testCreatePetInvalidJson() { String invalidJson = """ { "id": 123456, "name": "Invalid Pet", "category": { "id": 1, "name": "Dogs" }, "photoUrls": [ "http://example.com/photo.jpg" ], "tags": [ { "id": 0, "name": "string" } ], "status": "available" """; // отсутствует закрывающая фигурная скобка given() .contentType(ContentType.JSON) .body(invalidJson) .when() .post("/pet") .then() .statusCode(anyOf(is(400), is(405))); } /** * Реализация TestWatcher для логирования результата каждого теста. * Выводит сообщения: если тест пройден – "Test Passed", иначе "Test Failed", "Test Aborted" или "Test Disabled". */ public static class TestResultLogger implements TestWatcher { @Override public void testSuccessful(ExtensionContext context) { System.out.println(context.getDisplayName() + " - Passed"); } @Override public void testFailed(ExtensionContext context, Throwable cause) { System.out.println(context.getDisplayName() + " - Failed: " + cause.getMessage()); } @Override public void testAborted(ExtensionContext context, Throwable cause) { System.out.println(context.getDisplayName() + " - Aborted"); } @Override public void testDisabled(ExtensionContext context, Optional reason) { System.out.println(context.getDisplayName() + " - Disabled: " + reason.orElse("No reason provided")); } } }