From ea0c2c9f7e676e9c9890f00c210c2dbc9656d9f7 Mon Sep 17 00:00:00 2001 From: spawn Date: Fri, 16 May 2025 02:05:04 +0300 Subject: [PATCH] automated tests using Rest-assured --- .gitignore | 41 +++++ pom.xml | 96 ++++++++++ .../java/ru/otus/petstore/PetStoreTests.java | 170 ++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/test/java/ru/otus/petstore/PetStoreTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..04eafc6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +/.idea/ +/.mvn/ +/.gitignore diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..48ef708 --- /dev/null +++ b/pom.xml @@ -0,0 +1,96 @@ + + + + 4.0.0 + + + ru.otus + petstore + 1.0-SNAPSHOT + jar + petstore + + + + + 24 + 24 + UTF-8 + + 4.5.1 + 5.9.1 + + + + + + + io.rest-assured + rest-assured + ${restassured.version} + test + + + commons-codec + commons-codec + + + + + + + commons-codec + commons-codec + 1.15 + test + + + + + io.rest-assured + json-path + ${restassured.version} + test + + + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + + + + + + + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + maven-surefire-plugin + 2.22.2 + + + + diff --git a/src/test/java/ru/otus/petstore/PetStoreTests.java b/src/test/java/ru/otus/petstore/PetStoreTests.java new file mode 100644 index 0000000..1d93742 --- /dev/null +++ b/src/test/java/ru/otus/petstore/PetStoreTests.java @@ -0,0 +1,170 @@ +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). + */ + @Test + @Order(4) + @DisplayName("4. Test: Create pet missing '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 = "{\n" + + " \"id\": 123456,\n" + + " \"name\": \"Invalid Pet\",\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(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")); + } + } +}