REST Assured.Day 1

Коротко про REST API
Введення в REST Assured:
Ознайомитись із REST Assured
Приклад коду для встановлення REST Assured
Написання першого тесту

Коротко про REST API

REST (Representational State Transfer) API – це архітектурний стиль для розробки мережевих програм, заснований на принципах HTTP. Він дозволяє взаємодіяти з віддаленими серверами, обмінюючись даними у форматі JSON або XML.

Основні принципи REST API:

  1. Ресурси: Об'єкти або дані, до яких можна отримати доступ або модифікувати. Кожен ресурс ідентифікується унікальною URL-адресою.

  2. HTTP методи: REST використовує основні HTTP методи для операцій з ресурсами:

    • GET: Отримання даних.
    • POST: Створення нових даних.
    • PUT: Оновлення наявних даних.
    • DELETE: Видалення даних.
  3. Подання ресурсів::Ресурси передаються між клієнтом та сервером у форматі JSON або XML.

  4. Без стану (Stateless): Кожен запит на сервер повинен містити всю необхідну інформацію для виконання цього запиту. Сервер повинен зберігати стан клієнта між запитами.

  5. Однозначність (Uniform Interface):: Інтерфейс повинен бути однаковим для всіх ресурсів

  6. Шар взаємодії (Layered System): Клієнт не повинен знати про будь-які проміжні шари між ним і сервером.

REST API є популярним вибором для створення веб-сервісів через свою простоту, масштабованість та гнучкість. Він широко застосовується у розробці мобільних додатків, веб-додатків.

Вступ до REST Assured

REST Assured – це бібліотека для тестування RESTful веб-сервісів Java. Вона надає можливості для створення, надсилання та перевірки HTTP запитів та відповідей.

Основні переваги REST Assured:
Легко використовувати: не вимагає знання специфічних мов програмування чи фреймворків.
Можливість тестувати будь-які методи HTTP: GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH

-Підтримка автентифікації: Basic, OAuth, Digest, NTLM, Form.
-Підтримка серіалізації/десеріалізації JSON та XML.

Можливість перевіряти відповіді за допомогою специфічних умов.
-Можливість тестування запитів із параметрами, заголовками, тілом запиту та тілом відповіді.

Основні функції REST Assured:
-Створення та надсилання запитів HTTP.

-Перевірка відповідей HTTP

Парсинг та перевірка JSON або XML відповідей.
-Підтримка аутентифікації.

Підтримка серіалізації/десеріалізації JSON та XML.

-Підтримка файлів для мультипартів.

Підтримка Cookies.
Підтримка сесій.

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>

Встановлення та налаштування IntelliJ IDEA

Щоб налаштувати IntelliJ IDEA для тестування RESTful API за допомогою REST Assured, вам знадобиться виконати кілька кроків. Ось покрокова інструкція:

Крок 1: Встановлення IntelliJ IDEA Community Edition

Якщо ви ще не встановили IntelliJ IDEA Community Edition, ви можете зробити це за наступним: https://www.jetbrains.com/idea/download/

Крок 2: Налаштування Java Development Kit (JDK)

Якщо у вас ще не встановлено JDK, ви можете завантажити його з офіційного сайту Oracle: https://www.oracle.com/java/technologies/javase-jdk11-downloads.html

Крок 3: Встановлення Maven

Якщо у вас ще не встановлений Maven, ви можете завантажити його з офіційного сайту Apache Maven: https://maven.apache.org/download.cgi

Крок 4: Створення нового проекту Maven у IntelliJ IDEA

  1. Відкрийте IntelliJ IDEA (версія 2024.1) і виберіть File -> New -> Project.

  2. Виберіть проєкт Java.

  3. Вкажіть назву проєкту у полі "Name".

  4. У Build System виберіть Maven як тип проекту.

  5. Виберіть версію JDK.

  6. Натисніть "Create"

Додавання залежностей REST Assured та JUnit у файл pom.xml

Відкрийте файл pom.xml у кореневій директорії проекту та додайте наступну залежність до розділу :

<!— https://mvnrepository.com/artifact/io.rest-assured/rest-assured —>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>

Додати ще залежність jUnit.
JUnit — фреймворк для написання автоматизованих тестів Java. JUnit дозволяє створювати та запускати тестові випадки для перевірки свого коду. У контексті цього проекту JUnit використовується для написання та запуску тестових випадків REST API з використанням REST Assured.

<!— https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine —>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>

Створення тестового класу

 

  1. У IntelliJ IDEA перейдіть до папки src/test/java (якщо ні, то створіть).
  2. Правою кнопкою миші на папці java виберіть New -> Java Class.
  3. Введіть назву класу, наприклад BookingAPITest.

Написання тестів із використанням REST Assured

Ось приклад тесту, який використовує REST Assured для виконання GET-запиту до API:

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

public class BookingAPITest {

@BeforeAll
public static void setup() {
RestAssured.baseURI = «https://restful-booker.herokuapp.com»;
}

@Test
public void testGetBookingById() {
given()
.pathParam(«id», 1)
.when()
.get(«/booking/{id}»)
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body(«firstname», equalTo(«Susan»))
.body(«lastname», equalTo(«Brown»))
.body(«totalprice», equalTo(374))
.body(«depositpaid», equalTo(true))
.body(«bookingdates.checkin», equalTo(«2024-05-01»))
.body(«bookingdates.checkout», equalTo(«2024-05-10»))
.body(«additionalneeds», equalTo(«Breakfast»));
}

Цей код – це простий приклад тестування API з використанням бібліотеки REST Assured у середовищі JUnit 5. Давайте розберемо його:

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

Імпорт необхідних класів із бібліотеки REST Assured та JUnit 5.

public class BookingAPITest {

@BeforeAll
public static void setup() {
RestAssured.baseURI = «https://restful-booker.herokuapp.com»;
}

Оголошення класу тесту та методу ініціалізації (@BeforeAll), який виконуватиметься перед виконанням усіх тестів. Метод setup() встановлює базовий URI всім запитів. В даному випадку, використовується API сервіс для бронювання на сайті https://restful-booker.herokuapp.com.

 @Test
public void testGetBookingById() {
given()
.pathParam(«id», 1)
.when()
.get(«/booking/{id}»)
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body(«firstname», equalTo(«Susan»))
.body(«lastname», equalTo(«Brown»))
.body(«totalprice», equalTo(374))
.body(«depositpaid», equalTo(true))
.body(«bookingdates.checkin», equalTo(«2024-05-01»))
.body(«bookingdates.checkout», equalTo(«2024-05-10»))
.body(«additionalneeds», equalTo(«Breakfast»));
}

Метод тестування testGetBookingById(). В даному випадку він виконує GET-запит для отримання інформації про бронювання за ID.

  • given(): Вказує початковий стан запиту
    • .pathParam("id", 1): Встановлює параметр шляху (path parameter) з іменем «id» і значенням 1.
  • when(): Виконує запит.
    • .get("/booking/{id}"): Виконує GET-запит за адресою "/booking/{id}".
  • then(): Перевіряє відповідь на запит.
    • .statusCode(200): Перевіряє, чи статус-код відповіді дорівнює 200 (OK).
    • .contentType(ContentType.JSON): Перевіряє, чи тип вмісту відповіді JSON.
    • .body("firstname", equalTo("Susan")): Перевіряє, що значення поля "firstname" у відповіді дорівнює "Susan".
    • .body("lastname", equalTo("Brown")): Перевіряє, що значення поля "lastname" у відповіді дорівнює "Brown".
    • .body("totalprice", equalTo(374)): Перевіряє, що значення поля «totalprice» у відповіді дорівнює 374
    • .body("depositpaid", equalTo(true)): Перевіряє, що значення поля "depositpaid" у відповіді дорівнює true.
    • .body("bookingdates.checkin", equalTo("2024-05-01")): Перевіряє, що значення поля "checkin" в об'єкті "bookingdates" у відповіді дорівнює "2024-05-01".
    • .body("bookingdates.checkout", equalTo("2024-05-10")): Перевіряє, що значення поля "checkout" в об'єкті "bookingdates" у відповіді дорівнює "2024-05-10".
    • .body("additionalneeds", equalTo("Breakfast")): Перевіряє, що значення поля "additionalneeds" у відповіді дорівнює "Breakfast".

Практична частина

  1. Вивчити документацію
  2. Скласти тест-кейси
  3. Написати автотести

Документація REST API

Перед початком написання тестів необхідно ретельно вивчити документацію REST API. Без цього етапу неможливо скласти тест-кейси, які охоплюють всі сценарії використання. У документації ви знайдете всі необхідні ендпоінти, методи запитів, параметри та відповіді. Це дозволить вам глибоко зрозуміти, як взаємодіяти з API, і переконатися, що ваші тести повноцінно покриватимуть функціональність, за винятком помилок у роботі.

Складання тест-кейсів з отримання токена

Кроки:

Надіслати POST-запит на /auth з коректними обліковими даними:

«username»: «admin»
«password»: «password123»

Expected result:

  • Статус-код: 200 OK
  • Відповідь містить токен

Кроки:

Надіслати POST-запит на /auth з неправильним ім'ям користувача:

«username»: «admin1»
«password»: «password123»

Expected result:

  • Статус-код: 200 OK
  • Відповідь містить повідомлення про помилку

Кроки:

Надіслати POST-запит на /auth з неправильним паролем:

«username»: «admin»
«password»: «password1234»

Expected result:

  • Статус-код: 200 OK
  • Відповідь містить повідомлення про помилку

Кроки:

Надіслати POST-запит на /auth з довільними обліковими даними.

Expected result:

  • Час відповіді менше 3000 мс

Написання автотесту з тест-кейсів з коментарями

package activities; // Declaration of the package where this class is located

import io.restassured.RestAssured; // Importing the RestAssured class from the rest-assured library
import io.restassured.http.ContentType; // Importing the ContentType class from the rest-assured library
import io.restassured.response.ValidatableResponse; // Importing the ValidatableResponse class from the rest-assured library
import org.junit.jupiter.api.Assertions; // Importing the Assertions class from the JUnit Jupiter library
import org.junit.jupiter.api.DisplayName; // Importing the DisplayName annotation from the JUnit Jupiter library
import org.junit.jupiter.api.Test; // Importing the Test annotation from the JUnit Jupiter library

import static org.hamcrest.Matchers.lessThan; // Static import of the lessThan() method from the Matchers class in the Hamcrest library

public class AuthActivities { // Declaration of the AuthActivities class
private String baseUrl = «https://restful-booker.herokuapp.com»; // Defining the base URL for the API
private String basePath = «/auth»; // Defining the base path for the API

// Test to get a token with valid credentials
@Test // Annotation indicating that this method is a test
@DisplayName(«Get token with valid credentials») // Annotation specifying the display name for this test
public void test1() { // Method declaration for test1()
// Arrange
String body = «»»
{
«username» : «admin»,
«password» : «password123»
}
«»»; // Defining a JSON string to be sent in the request. It contains the username and password.

// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.body(body) // Passing the request body
.log().all() // Logging all actions
.when() // Completing the request setup and starting its execution
.post() // Sending a POST request
.then() // Starting response validation
.log().all(); // Logging all actions

// Assert
Assertions.assertNotNull(response.extract().asString()); // Checking that the response is not null
Assertions.assertTrue(response.extract().asString().contains(«token»)); // Checking for the presence of «token» in the response
}

// Test to get a token with an invalid username
@Test // Annotation indicating that this method is a test
@DisplayName(«Get token with invalid username») // Annotation specifying the display name for this test
public void test2() { // Method declaration for test2()
// Arrange
String body = «»»
{
«username» : «admin1»,
«password» : «password123»
}
«»»; // Defining a JSON string to be sent in the request. It contains an incorrect username

// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.body(body) // Passing the request body
.when() // Completing the request setup and starting its execution
.post() // Sending a POST request
.then(); // Starting response validation

// Assert
Assertions.assertNotNull(response.extract().asString()); // Checking that the response is not null
Assertions.assertTrue(response.extract().asString().contains(«reason»)); // Checking for the presence of «reason» in the response
}

// Test to get a token with an invalid password
@Test // Annotation indicating that this method is a test
@DisplayName(«Get token with invalid password») // Annotation specifying the display name for this test
public void test3() { // Method declaration for test3()
// Arrange
String body = «»»
{
«username» : «admin»,
«password» : «password1234»
}
«»»; // Defining a JSON string to be sent in the request. It contains an incorrect password

// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.body(body) // Passing the request body
.when() // Completing the request setup and starting its execution
.post() // Sending a POST request
.then(); // Starting response validation

// Assert
Assertions.assertNotNull(response.extract().asString()); // Checking that the response is not null
Assertions.assertTrue(response.extract().asString().contains(«reason»)); // Checking for the presence of «reason» in the response
}

// Test to check the response time is less than 3000ms
@Test // Annotation indicating that this method is a test
@DisplayName(«Response time less than 3000ms») // Annotation specifying the display name for this test
public void test5() { // Method declaration for test5()
// Arrange
String body = «»»
{
«username» : «admin»,
«password» : «password1234»
}
«»»; // Defining a JSON string to be sent in the request. It contains an incorrect password

// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.body(body) // Passing the request body
.when() // Completing the request setup and starting its execution
.post() // Sending a POST request
.then(); // Starting response validation

// Assert
response.assertThat().time(lessThan(3000L)); // Checking that the response time is less than 3000ms
}
}

Складання тест-кейсів з отримання всіх бронювань

Кроки:

Надіслати GET-запит на ендпоінт /booking.

Expected result:

    • Перевірити, що відповідь має поле «bookingid».
    • Перевірити, що відповідь не пуста.

Кроки:

Надіслати GET-запит на ендпоінт /booking.

Expected result:

    • Перевірити, чи статус коду відповіді 200 (OK).

Кроки:

Надіслати GET-запит на ендпоінт /booking.

Expected result:

    • Перевірити, що час відповіді менше 3000 мс.

Кроки:

Надіслати GET-запит на ендпоінт /booking.

Expected result:

    • Перевірити, чи відповідь відповідає схемі, вказаній у файлі «bookingGetAllResponseSchema.json».

Написання автотесту з тест-кейсів з коментарями

package activities; // Declaration of the package where this class is located

import io.restassured.RestAssured; // Importing the RestAssured class from the rest-assured library
import io.restassured.http.ContentType; // Importing the ContentType class from the rest-assured library
import io.restassured.response.ValidatableResponse; // Importing the ValidatableResponse class from the rest-assured library
import org.junit.jupiter.api.Assertions; // Importing the Assertions class from the JUnit Jupiter library
import org.junit.jupiter.api.DisplayName; // Importing the DisplayName annotation from the JUnit Jupiter library
import org.junit.jupiter.api.Test; // Importing the Test annotation from the JUnit Jupiter library

import static com.jayway.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; // Importing the matchesJsonSchemaInClasspath() method from the JsonSchemaValidator class in the rest-assured library
import static org.hamcrest.Matchers.lessThan; // Static import of the lessThan() method from the Matchers class in the Hamcrest library

public class GetActivities { // Declaration of the GetActivities class
private String baseUrl = «https://restful-booker.herokuapp.com»; // Defining the base URL for the API
private String basePath = «/booking»; // Defining the base path for the API

// Test to get all bookings
@Test // Annotation indicating that this method is a test
@DisplayName(«Get All Bookings») // Annotation specifying the display name for this test
public void test1() { // Method declaration for test1()
// Arrange
// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.when() // Completing the request setup and starting its execution
.get() // Sending a GET request
.then() // Starting response validation
.log().all(); // Logging all actions

// Assert
Assertions.assertNotNull(response.extract().asString()); // Checking that the response is not null
Assertions.assertTrue(response.extract().asString().contains(«bookingid»)); // Checking for the presence of «bookingid» in the response
}

// Test to check if the status code is 200
@Test // Annotation indicating that this method is a test
@DisplayName(«Status code is 200») // Annotation specifying the display name for this test
public void test2() { // Method declaration for test2()
// Arrange
// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.when() // Completing the request setup and starting its execution
.get() // Sending a GET request
.then(); // Starting response validation

// Assert
response.assertThat().statusCode(200); // Checking that the status code is 200
}

// Test to check if the response time is less than 3000ms
@Test // Annotation indicating that this method is a test
@DisplayName(«Response time less than 3000ms») // Annotation specifying the display name for this test
public void test3() { // Method declaration for test3()
// Arrange
// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.when() // Completing the request setup and starting its execution
.get() // Sending a GET request
.then(); // Starting response validation

// Assert
response.assertThat().time(lessThan(3000L)); // Checking that the response time is less than 3000ms
}

// Test to check if the response matches the defined schema
@Test // Annotation indicating that this method is a test
@DisplayName(«Response matches schema») // Annotation specifying the display name for this test
public void test4() { // Method declaration for test4()
// Arrange
// Act
ValidatableResponse response = RestAssured // Invoking RestAssured to send an HTTP request
.given() // Starting a chain of calls to set up the request
.basePath(basePath) // Setting the base path for the request
.baseUri(baseUrl) // Setting the base URL for the request
.contentType(ContentType.JSON) // Setting the request content type as JSON
.when() // Completing the request setup and starting its execution
.get() // Sending a GET request
.then(); // Starting response validation

// Assert
response.assertThat().body(matchesJsonSchemaInClasspath(«bookingGetAllResponseSchema.json»)); // Checking that the response matches the defined schema
}
}

Самостійна робота

  • Вивчити документацію
  • Дописати тест-кейси з отримання токена та бронювань
  • Дописати автотести

Також є можливість завантажити проєкт

Але краще напишіть все вручну

Підтримка та питання

Якщо у вас виникли проблеми із запуском тестів або у вас є інші питання, не соромтеся звертатися до нас.

Через чат-бот

Надсилання завдання

Після завершення написання тестів, будь ласка, архівуйте ваш проект у форматі ZIP або RAR та надішліть нам для перевірки.