Guía importante para pruebas de API Rest y RestAssured

En este exhaustivo tutorial de Rest Assured vamos a aprender los Rest API Testing en profundidad, API Test Automation junto con Rest Assured en un enfoque modular

Qué es RestAssured y su uso

Rest Assured es una tecnología de código abierto muy utilizada para las pruebas de automatización de API REST, que se basa en una biblioteca basada en Java.

Rest Assured interactúa con Rest API en un modo de cliente sin cabeza, podemos mejorar la misma solicitud agregando diferentes capas para formar la solicitud y crear una solicitud HTTP a través de diferentes verbos HTTPS en el servidor.

La biblioteca integrada Rest Assured proporciona enormes métodos y utilidades para realizar la validación de la respuesta recibida del servidor, como el mensaje de estado, el código de estado y el cuerpo de la respuesta.

Esta serie completa de tutoriales Rest Assured para pruebas de automatización de API REST consta de los siguientes temas:

RestAssured: el tutorial de pruebas de API puede estar seguro
Automatización de API con tranquilidad

Introducción: configuración de restAssured con la herramienta de compilación, es decir, Maven / gradle

PASO 1: Si está trabajando con maven, simplemente agregue la siguiente dependencia en pom.xml (también puede elegir cualquier otra versión):

Para comenzar con REST Assured, simplemente agregue la dependencia a su proyecto. 


    io.rest-asegurado
    Está seguro
    4.3.0
    prueba

Si está trabajando con gradle, simplemente agregue lo siguiente en build.gradle (nuevamente, puede elegir cualquier otra versión):

testCompile grupo: 'io.rest-secure', nombre: 'rest-sure', versión: '4.3.0'

PASO 2: REST Assured se puede integrar y usar muy fácilmente con los marcos de prueba unitarios existentes, es decir, Testng, JUnit

Aquí estamos usando testNg según el marco de prueba unitario.

Una vez que se importan las bibliotecas de Rest Assured, debemos agregar las siguientes importaciones estáticas a nuestras clases de prueba:

importar static io.restassured.RestAssured. *;

importar org.hamcrest.Matchers estáticos. *;

NOTA: Para este próximo propósito de aprendizaje, probaremos la API de Ergast Developer, que se puede encontrar aquí. Esta API proporciona datos históricos relacionados con carreras, pilotos, circuitos, etc. de Fórmula 1.

Familiaridad con la sintaxis:

Rest Assured es compatible con el formato BDD (Sintaxis de pepinillo) para escribir los scripts de prueba, es decir, en formato Dado / Cuándo / Entonces / Y, asumimos que tiene comprensión sobre la sintaxis BDD / pepinillo, si no, le sugerimos que dedique 30 minutos de tiempo a comprender qué es BDD (Sintaxis de pepinillo) y cómo funciona y es muy básico.

T-01: Nuestro primer script, que básicamente está validando el número de circuitos en F1 en 1 utilizando esta API (http://ergast.com/api/f1/2017/circuits.json)

@Test (description = "El número de circuitos en la temporada 2017 debe ser 20") public void validatingNumberOfCircuits () {given (). When (). Get ("http://ergast.com/api/f1/2017/circuits. json "). then (). assertThat (). body ("MRData.CircuitTable.Circuits.circuitId", hasSize (20)); }

Validación de respuesta de API de descanso :

1. Captura la respuesta JSON de la solicitud de API.

2. Consultas para circuitId utilizando la expresión GPath "MRData.CircuitTable.Circuits.circuitId"

3. Verifica que la colección de elementos de circuitId tenga el tamaño de 20

Aquí estamos usando Emparejadores de Hamcrest para varias validaciones como

Hay varios otros métodos que son útiles para realizar cierta validación.

Además, puede consultar la documentación de la biblioteca de Hamcrest para obtener una lista completa de comparadores y métodos.

Validando el código de respuesta:

dado (). cuando (). obtener ("http://ergast.com/api/f1/2017/circuits.json"). then (). assertThat (). statusCode (200);

Validación del tipo de contenido

dado (). when (). get ("http://ergast.com/api/f1/2017/circuits.json") .then (). assertThat (). contentType (ContentType.JSON);

Validando el encabezado "Contenido-Longitud"

dado (). cuando (). obtener ("http://ergast.com/api/f1/2017/circuits.json"). then (). assertThat (). header (" Content-Length ", equalTo (" 4551 "));

Validación múltiple en una sola prueba como (mediante el uso de métodos y ()):

@Test (description = "El número de circuitos en la temporada 2017 debería ser 20")
    public void validatingNumberOfCircuits () {
        dado (). when (). get ("http://ergast.com/api/f1/2017/circuits.json"). then (). assertThat (). header ("Content-Length", equalTo (" 4551 ")). Y (). StatusCode (200);
    }

Validación del elemento / atributo del cuerpo de respuesta:

Podemos usar JsonPath para obtener el valor de los atributos json y poner aserción usando TestNg

@Test (description = "Validación del nombre de la serie que es f1")
    public void validatingSeriesName () {
        // Convertir ResponseBody en String
        String responseBody = dado (). When (). Get ("http://ergast.com/api/f1/2017/circuits.json") .getBody (). AsString ();
        // Cree el objeto JsonPath pasando el cuerpo de respuesta como una cadena
        JsonPath resJson = new JsonPath (responseBody);
        // Obtener la serie de valores de atributo en MRData
        String seriesName = resJson.getString ("MRData.series");
        // Aserción TestNg del usuario
        Assert.assertEquals ("f1", seriesName);
    }

De manera similar, podríamos obtener el valor de la respuesta XML usando XMLPath. Aquí estamos trabajando con JSON, por lo tanto, usamos aquí JSonPath

Las API RESTful solo admiten dos tipos de parámetros:

A. Parámetros de consulta: Aquí, los parámetros se añaden al final del punto final de la API y podrían identificarse con el signo de interrogación y forman un par clave-valor como 

https://www.google.com/search?q=https://www.wikipedia.org/

Aquí, en la API anterior, 'q' es el parámetro y 'https://www.wikipedia.org/' es el valor de ese parámetro, si buscamos 'ALGO_ELSE_TEXT'podríamos reemplazar el valor del parámetro 'q' con "ALGO_ELSE_TEXT'en lugar de https://www.wikipedia.org/.

B. Parámetros de ruta: Estos son parte del punto final de la API RESTful. 

p.ej. punto final que usamos anteriormente: http://ergast.com/api/f1/2017/circuits.json, aquí "2017" es un valor de parámetro de ruta.

Para obtener un resultado del año 2016 podríamos reemplazar 2017 con 2016 luego, la API dará el cuerpo de respuesta para 2016.

Pruebas con Path Params para RestAssured

@Test (description = "Validación del número de circuitos usando parámetros de ruta")
    public void testWithPathParams () {
        String seasonNumber = "2017";
       String responseBody = given (). PathParam ("season", seasonNumber) .when (). Get ("http://ergast.com/api/f1/{season}/circuits.json") .getBody (). AsString ();
        // Cree el objeto JsonPath pasando el cuerpo de respuesta como una cadena
        JsonPath resJson = new JsonPath (responseBody);
        // Obtener la serie de valores de atributo en MRData
        String seriesName = resJson.getString ("MRData.series");
        // Aserción TestNg del usuario
        Assert.assertEquals ("f1", seriesName);
    }

Pruebas con Query Params para RestAssured

@Test (description = "Validación de la búsqueda de Google mediante los parámetros de consulta")
    public void testWithPathParams () {
        String searchItem = "https://www.wikipedia.org/";
  dado (). queryParam ("q", searchItem) .when (). get ("https://www.google.com/search") .then (). assertThat (). statusCode (200);
    }

Pruebas de parametrización:

Podemos hacer pruebas basadas en datos (es decir, el mismo script de prueba se ejecutará varias veces con diferentes conjuntos de datos de entrada y proporcionará diferentes datos de salida) utilizando Rest Assured 

PASO 1: Creó un proveedor de datos de prueba.

PASO 2: Consuma el proveedor de datos en el script de prueba.

@DataProvider (name = "seasonsAndRaceNumbers")
    Objeto público [] [] testDataFeed () {
        devolver nuevo objeto [] [] {
                {"2017", 20},
                {"2016", 21}
        };
    }
@Test (description = "Validación del número de circuitos en diferentes estaciones", dataProvider = "temporadas y números de carrera") public void circuitNumberValidation (String seasonYear, int raceNumbers) {dado ().pathParam ("temporada", seasonYear) .when (). get ("http://ergast.com/api/f1/{temporada}/circuits.json "). then (). assertThat (). body (" MRData.CircuitTable.Circuits.circuitId ", hasSize (números de carrera)); }

Trabajar con parámetros de valores múltiples con RestAssured 

Los parámetros de valores múltiples son aquellos parámetros que tienen más de un valor por nombre de parámetro (es decir, una lista de valores por paramKey), podemos abordarlos de la siguiente manera:

dado (). param ("paramKey", "paramValue1", "paramaValue2"). when (). get (“API URL“);

O podríamos preparar una lista y pasar la lista como el valor de paramKey como:

Lista paramValue = new new ArrayList ();
paramValue.add ("paramvalue1");
paramValue.add (“paramvalue2);
dado (). param ("paramKey", paramValue) .when (). get ("API URL");
Trabajar con cookies con RestAssured 
dado (). cookie ("cookieK", "cookieVal"). when (). get ("API URL");

Or 

También podemos especificar una cookie de varios valores aquí como:

dado (). cookie ("cookieK", "cookieVal1", "cookieVal2"). when (). get ("API URL");

Trabajar con encabezados:

Podemos especificar en una solicitud usando encabezados / encabezados como:

dado (). header ("headerK1", "headerValue1"). header ("headerK2", "headerValue2"). when (). get ("API URL");

Trabajar con contentType:

dado (). contentType ("aplicación / json"). when (). get ("API URL");

Or 

dado (). contentType (ContentType.JSON) .when (). get ();

Mida el tiempo de respuesta:

long timeDurationInSeconds = get ("URL API"). timeIn (SEGUNDOS);

Autenticación de API de descanso

REST Guaranteed admite diferentes esquemas de autenticación, por ejemplo, OAuth, digest, certificado, formulario y autenticación básica preventiva. Podemos configurar la autenticación para todas y cada una de las solicitudes 

aquí hay una solicitud de muestra usando el mismo:

dado (). auth (). basic ("uName", "pwd"). when (). get (“URL“) ..

Por otro lado, la autenticación y se define en el siguiente enfoque para las solicitudes HTTP:

RestAssured.authentication = basic ("uName", "pwd");

Tipos de AUTH básicos:

Hay dos tipos de autenticación básica, "preventiva" y "autenticación básica de token desafiado".

Autorización básica preventiva:

Esto enviará la credencial de autenticación básica incluso antes de que el servidor dé una respuesta no autorizada en determinadas situaciones junto con la activación de la solicitud, reduciendo así la sobrecarga de realizar una conexión adicional. Por lo general, se trata de situaciones que ocurren de manera importante, a menos que estemos probando la capacidad de los servidores para desafiar. 

Por ejemplo.

dado (). auth (). preventivo (). básico ("uName", "pwd"). when (). get ("URL"). then (). statusCode (200);

Autenticación básica desafiada

Por otro lado, REST Assured, “autenticación básica cuestionada”, no proporcionará las credenciales a menos que el servidor las haya solicitado explícitamente, es decir, el servidor arroja la Respuesta no autorizada. Después de esa respuesta no autorizada, Rest-Assured envía otra solicitud al servidor que es el Auth.

dado (). auth (). basic ("uName", "pwd"). when (). get ("URL"). then (). statusCode (200);

Autenticación implícita

A partir de ahora, solo se está considerando la "autenticación implícita impugnada". p.ej:

dado (). auth (). digest ("uName", "pwd"). when (). get ("URL"). then (). statusCode (200); 

Autenticación de formularios

Podríamos lograr esto principalmente en 3 enfoques diferentes según la Aplicación / Escenarios:

La autenticación de formularios es una de las más populares en Internet, es decir, un usuario ingresa sus credenciales, es decir, nombre de usuario y contraseña a través de una página web e inicia sesión en el sistema. 

dado (). auth (). formulario ("uName", "pWd").
when (). get ("URL");
luego (). statusCode (200);

Si bien esto puede no funcionar, ya que es óptimo y puede aprobarse o fallar según la complejidad de la página web. Una mejor opción es proporcionar estos detalles al configurar la autenticación del formulario en el siguiente enfoque:

given (). auth (). form ("uName", "pwd", new FormAuthConfig ("/ 'mencione aquí el nombre de la acción del formulario que es parte del código de página html y la etiqueta del formulario'", "uName", "pwd ")). when (). get (" URL "). then (). statusCode (200);

En este enfoque, el REST asegurado internamente no requerirá activar una solicitud adicional y analizar a través de la página web. 

Si, en caso de que esté utilizando Spring Security predeterminado, entonces se activa un FormAuthConfig predefinido.

dado (). auth (). form ("uName", "Pwd", FormAuthConfig.springSecurity ()). when (). get ("URL"). then (). statusCode (200);

NOTA: Si queremos enviar datos de entrada adicionales junto con la autenticación del formulario, podemos escribir lo siguiente:

given (). auth (). form ("uName", "pwd", formAuthConfig (). withAdditionalFields ("firstInputField", "secondInputField"). ..

CSRF:

CSRF son las siglas de Cross-site request forgery.

Hoy en día es muy común que el servidor proporcione un token CSRF con la respuesta para evitar los ataques de seguridad CSRF. REST Assured admite esto mediante el uso de un analizador automático y proporcionando un token CSRF. 

Para lograr este REST Assured es necesario realizar una solicitud adicional y analizar (pocas posiciones) del sitio web.

Podemos habilitar el soporte CSRF escribiendo el siguiente código:

dado (). auth (). form ("uName", "pwd", formAuthConfig (). withAutoDetectionOfCsrf ()). when (). get ("URL"). then (). statusCode (200);

Además, para ayudar a REST Assured y hacer que el análisis sea más impecable y robusto, podemos proporcionar el nombre del campo CSRF (aquí asumimos que estamos usando valores predeterminados de Spring Security y podríamos usar springSecurity FormAuthConfig predefinido):

dado (). auth (). form ("uName", "pwd", springSecurity (). withCsrfFieldName ("_ csrf")). when (). get ("URL"). then (). statusCode (200);

De forma predeterminada, el valor CSRF se pasa como un parámetro de formulario con la solicitud, pero podemos configurarlo para enviarlo como un encabezado si en caso de que sea necesario, como se muestra a continuación:

dado (). auth (). form ("uName", "pwd", springSecurity (). withCsrfFieldName ("_ csrf"). sendCsrfTokenAsHeader ()). when (). get ("URL"). then (). statusCode (200);

OAuth 1:

OAuth 1 requiere que Scribe esté en la ruta de clases. Para usar la autenticación oAuth 1 podemos hacer:

dado (). auth (). oauth (..). when (). ..

OAuth 2:

dado (). auth (). oauth2 (accessToken) .when (). ..

En el enfoque anterior, el accessToken de OAuth2 se considerará en un encabezado. Para ser más explícitos también podemos hacer:

dado (). auth (). preemptive (). oauth2 (accessToken) .when (). ..

Pasando archivo, matriz de bytes, flujo de entrada o texto en la solicitud:

Cuando se envían grandes cantidades de datos al servidor, generalmente es un enfoque común utilizar la técnica de datos de formularios de varias partes. Rest Assured proporciona métodos llamados multiPart que nos permiten especificar un archivo, matriz de bytes, flujo de entrada o texto para cargar. 

dado (). multiPart (new File ("/ File_Path")). when (). post ("/ upload");

Creación de solicitudes POST con descanso asegurado

Con las solicitudes POST y PUT, enviamos datos al servidor y su básicamente creación de recursos / actualización de recursos, puede considerar esto como una operación de escritura o actualización.

Los datos que se envían al servidor en una solicitud POST se envían en el cuerpo de la solicitud HTTP / llamada API. 

El tipo de contenido o datos que se envían puede tener un formato diferente dependiendo de la API, es decir, XML, JSON o algún otro formato está definido por el encabezado Content-Type. 

Si el cuerpo POST consta de datos JSON, el tipo de contenido del encabezado será application / json. De manera similar, para una solicitud POST que consta de un XML, el tipo de contenido del encabezado sería de tipo application / xml.

Aquí está el siguiente fragmento de código para el mismo:

dado (). contentType ("application / json"). param ("pk", "pv"). when (). body ("JsonPAyloadString"). post ("url"). then (). assertThat (). statusCode (200);

NOTA: Hay diferentes formas en que podemos pasar la carga útil / cuerpo de solicitud dentro del método "cuerpo" como String (como se muestra en el fragmento anterior), JsonObject, como un archivo, etc.

Solicitud PUT con la tranquilidad de estar seguro:

dado (). contentType ("application / json"). param ("pk", "pv"). when (). body ("JsonPAyloadString"). put ("url"). then (). assertThat (). statusCode (200);

Eliminar solicitud con Rest-Assured:

dado (). contentType ("aplicación / json"). param ("pk", "pv"). when (). delete ("url"). then (). assertThat (). statusCode (200);

Y de esa manera podemos crear diferentes llamadas a la API Rest para diferentes verbos API (GET / POST / PUT / DELETE, etc.)

Serialización y deserialización en Java:

La serialización consiste básicamente en procesar o convertir el estado del objeto en un flujo de bytes. Por otro lado, la deserialización en Java está procesando o convirtiendo el flujo de bytes en un objeto Java real dentro de la memoria. Este mecanismo se utiliza en la persistencia de Object.

A continuación se muestra el diagrama de bloques para el mismo 

1ESLuGPTk5gUs9eA5 OXkbw KyHeRnO9TdX bg OEo3 ZD7BJ9HqLY HcOaf9saeK137JSzmDj7 TY2WmrlVogzLzkgmN1gvLvyaF6cdGb6psTcv0HVH98J45L4b1a0c3ucUvJ6p

Ventajas de la serialización

A. Guardar / conservar el estado de un objeto.

B. Hacer fluir un objeto a través de una red.

Lograr la serialización con JAVA

Para lograr un objeto Java serializable, necesitamos implementar la interfaz java.io.Serializable.

La clase ObjectOutputStream que contiene el método writeObject () responsable de serializar un objeto.

La clase ObjectInputStream también contiene otro método llamado readObject () que es responsable de deserializar un objeto.

clases que están implementando la interfaz java.io.Serializable, el objeto solo se puede serializar.

Serializable es solo una interfaz de marcador y, al igual que otras interfaces de mercado, no tiene ningún miembro de datos o método asociado, que se utiliza para "marcar" las clases de Java para que los objetos de estas clases obtengan ciertas capacidades. Como pocas otras interfaces de marcador son: - Clonable y Remoto, etc.

NOTAS:

1. Si una clase principal ha implementado una interfaz serializable, no se requiere que la clase secundaria implemente la misma pero viceversa no es aplicable.

2. Solo los miembros de datos no estáticos se almacenan con el proceso de serialización.

3. Los miembros de datos estáticos y también los miembros de datos transitorios no están siendo almacenados por la serialización. Por lo tanto, en caso de que no necesitemos almacenar el valor del miembro de datos no estáticos, podemos hacerlo transitorio.

4. Nunca se llama al constructor cuando se deserializa un objeto.

PASO 1: El primer paso es básicamente la creación de una clase que implementa la interfaz serializable:

importar java.io.Serializable;
public class Dummy implementa Serializable {
    privado int i;
    datos de cadena privados;
    public Dummy (int i, datos de cadena)
    {
        esto.i = yo;
        this.data = data;
    }
}

PASO 2: Cree una clase para serializarla:

importar java.io.FileNotFoundException;
importar java.io.FileOutputStream;
importar java.io.IOException;
importar java.io.ObjectOutputStream;
public class Serialize {
    serialización vacía estática pública (objeto classObject, String fileName) {
        tratar {
            FileOutputStream fileStream = nuevo FileOutputStream (nombre de archivo);
            ObjectOutputStream objectStream = nuevo ObjectOutputStream (fileStream);
            objectStream.writeObject (classObject);
            objectStream.close ();
            fileStream.close ();
        } captura (FileNotFoundException e) {
            // TODO Bloque de captura generado automáticamente
            e.printStackTrace ();
        } captura (IOException e) {
            // TODO Bloque de captura generado automáticamente
            e.printStackTrace ();
        }
    }
    principales argumentos (String []) {public static void
        Dummy dummyObj = new Dummy (10, "Lambda-geeks");
        Serialización (dummyObj, "DummSerialized");
    }
}

PASO 3: Una vez que el Paso 2 se complete con éxito, podrá ver que se creó un archivo con algunos datos, esos datos son básicamente datos serializados de los miembros del Objeto.

  Deserialización con java:

Aquí está el siguiente fragmento de código:

 public static Object DeSerialize (String fileName)
    {
        tratar {
            FileInputStream fileStream = new FileInputStream (nuevo archivo (nombre de archivo));
            ObjectInputStream objectStream = nuevo ObjectInputStream (fileStream);
            Object deserializeObject = objectStream.readObject ();
            objectStream.close ();
            fileStream.close ();
            volver deserializeObject;
        } captura (FileNotFoundException e) {
            e.printStackTrace ();
        } captura (IOException e) {
            e.printStackTrace ();
        } captura (ClassNotFoundException e) {
            e.printStackTrace ();
        }
        volver nulo;
    }

El código del conductor es el siguiente:

 principales argumentos (String []) {public static void
      / * Dummy dummyObj = new Dummy (10, "Lambda-geeks");
        Serialización (dummyObj, "DummSerialized");
        System.out.println ("------------------------------------------- ------------------------------- ");
      */
        Dummy deSerializedRect = (Dummy) DeSerialize ("DummSerialized");
        System.out.println ("Datos del objeto serializado" + deSerializedRect.print ());
        System.out.println ("------------------------------------------- ------------------------------- ");
    }

JSONPATH Más sintaxis / consulta:

Supongamos un JSON de la siguiente manera:

{
  "OrganizationDetails": "Detalles ficticios de la organización",
  "Región": "Asia",
  "Emp-Detalles": [
    {
      "Org": "lambda-Geeks",
      "Información": {
        "Ph": 1234567890,
        "Agregar": "XYZ",
        "Edad": 45
      }
    },
    {
      "Org": "lambda-Geeks-2",
      "Información": {
        "Ph": 2134561230,
        "Agregar": "ABC",
        "Edad": 35
      }
    }
  ]
}

en el JSON anterior, los detalles de la organización y la región se denominan nodo hoja porque no tienen más nodos / elementos secundarios, sino que, por otro lado, los detalles emp tienen un nodo secundario, por lo que no se denomina nodo hoja.

Aquí, si intentamos obtener el valor de OrganizationDetails, debemos usar:

$ .OrganizationDetails 
Esto resultará en:
 [
  "Detalles ficticios de la organización"
]

Como Wise para obtener los datos de la región, necesitamos escribir:

$ .Region 

Si queremos encontrar el valor de Edad para el primer empleado, podríamos escribir:

$ .Emp-Detalles [0] .Información.Edad
Esto resultará en:
[
  45
]

Para la edad del segundo empleado podríamos escribir como

$ .Emp-Detalles [1] .Información.Edad
Esto resultará en: [35]

De esta manera, podemos averiguar la expresión / consulta de JsonPath para obtener los datos de los campos respectivos en JSON.