Postman es una herramienta muy útil para probar las peticiones a APIs, tanto si las estamos desarrollando nosotros, como si son de otro proveedor, y poder así testear y comprobar los datos que se reciben en cada llamada. En este post, abordaré cómo incluir tests de validación para comprobar que las llamadas se reciben correctamente y que además, los datos que recibimos cumplen con un determinado schema JSON predefinido.

Este post forma parte de la serie de artículos sobre Postman, que empezamos con la automatización de la autenticación de APIs.

Comprobación del resultado de la llamada

El primer test y el más sencillo que podemos incorporar es validar que la llamada se ha realizado correctamente, y hemos recibido un Response 200 OK, o cualquier otro que estemos esperando. Para ello, la manera más sencilla es incluir este test a nivel de Collection, para que así todas las peticiones incluidas en la misma hereden este test. 

Para ello, editamos la colección y en la pestaña "Tests", incluimos el siguiente script:

pm.test("Status code is OK", function () {
    pm.expect(pm.response.code).to.be.oneOf([200, 201, 204, 207])
});

En la lista de códigos de respuesta podemos incluir todos los que necesitemos. Una vez configurado, si ejecutamos cualquier petición, podemos ver en la pestaña "Tests" de la respuesta el resultado del mismo:

Image1.png

Validación del schema JSON de la respuesta

El lenguage de scripting de Postman es muy versátil, y nos permite ir más allá de una simple comprobación del estado de la respuesta, y podemos incluir validaciones más complejas, como por ejemplo, comprobar que el contenido de la respuesta en JSON cumple con el schema predefinido que debe devolver dicha petición.

Para poder ejecutar esta validación, volvemos a la pestaña "Tests" de la Collection, y añadimos el siguiente script, a continuación del script anterior:

try 
{
    var schema = pm.variables.get("schema");

    if(schema)
    {
        const jsonData = pm.response.json();
        if(jsonData)
        {
            //const dateTimeRegex = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?$');
            var Ajv = require('ajv'),
            ajv = new Ajv({logger: console, allErrors: true});
            //ajv.addFormat('date-time', {
            //    validate: (dateTimeString) => dateTimeRegex.test(dateTimeString)
            //});
        
            pm.test('Schema is valid', function() {
                var validate = ajv.validate(schema, jsonData);
                console.log(ajv.errors);
                pm.expect(validate, JSON.stringify(ajv.errors)).to.be.true;
            });
        }
    }
}
catch(e){
    console.log(e);
}

Este script obtendrá el schema de una variable "schema", que luego definiremos, y validará el contenido de la respuesta de la petición contra dicho schema, utilizando la librería "Ajv". Como añadido, he dejado comentado cómo definir un formato de fecha específico, para validaciones que requieran un formato de fecha diferente.

El siguiente paso será obtener el schema que debe devolver la petición. Si disponemos del detalle del API que estamos consumiendo en en servicios como Apiary o Swagger, estos mismos servicios ya nos proporcionan el detalle del schema en su definición de cada petición. Si no disponemos de ellos, pero tenemos un objeto JSON válido, podemos utilizar herramientas online como Quicktype, para generar nuestro schema. En este ejemplo, podéis ver el schema generado para un json del API de Zendesk:

Image2 (Custom).png

Una vez que ya tenemos el schema, volvemos a Postman y seleccionamos la petición sobre la cual queremos validar su schema, y editamos la pestaña "Pre-request Script", donde incluimos el siguiente script (usando el schema obtenido con antelación):

var schema = {
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$ref": "#/definitions/ZendeskJobResult",
    "definitions": {
        "ZendeskJobResult": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "action": { "type": "string" },
                "id": { "type": "integer" },
                "status": { "type": "string" },
                "success": { "type": "boolean" }
            },
            "required": ["action", "id", "status", "success" ],
            "title": "ZendeskJobResult"
        }
    }
};

pm.variables.set("schema", schema);

Por defecto, es posible que nos defina todos los campos como "Required", por lo que tendremos que validar manualmente si es correcto, y modificarlo según nuestras necesidades. Estamos añadiendo el schema a una variable local, que luego guardamos como variable de ejecución. 

Este proceso tendremos que hacerlo para cada una de las peticiones que queramos validar, ya que por norma general, el schema de los datos devueltos por cada petición será diferente, pero sólo tenemos que definir el schema, ya que el script de validación lo hemos definido a nivel de Collection.

El funcionamiento es el siguiente:

  • Antes de iniciarse la petición, el script de "Pre-request Script" de la petición se ejecuta, y define el valor de la variable "schema"
  • Después de ejecutarse la petición, el script de "Tests" de la Collection se ejecuta, y utiliza la variable definida por la petición para validar la misma

Como resultado, podemos ver que la pestaña de Tests de la respuesta se ha ampliado con un segundo test:

Image3.png

En el caso de que no valide el schema, nos indicará cuál ha sido la propiedad que no cumple y el motivo:

Image6.png

En este caso, podemos ver que falta la propiedad "serviceList", que estaba marcada como requerida.

Ejecución de tests masivos

Una vez tenemos definidos estos tests de validación, podemos hacer uso de otra de las herramientas que incluye Postman para ejecutar validación por lotes de todas o un conjunto de las peticiones definidas en una Collection. Para ello, abrimos la herramienta Runner:

Image4.png

Elegimos la Collection a ejecutar, o la carpeta que queramos lanzar, incluso qué peticiones incluimos en la ejecución, el Environment sobre el que lo ejecutamos, así como el número de veces que se va a lanzar, el delay entre cada petición y algunos settings adicionales. Runner se encargará de lanzar todas las peticiones por nosotros, y mostrarnos un resumen de resultados de las mismas:

Image5.png

De esta manera, podemos lanzar de una forma sencilla todas nuestras peticiones y comprobar que todo sigue funcionando correctamente después de, por ejemplo, un despliegue a producción.