Implementación de escenarios avanzados de pruebas API con Postman

Las capacidades de scripting en Postman ofrecen flexibilidad extrema para pruebas API complejas. Basado en Postman 6.1.4 para Mac y usando una demo de API de usuario como ejemplo, exploramos cómo abordar varios escenarios desafiantes.

El caso de uso implica la depuración e integración continua de varias APIs de pedido, que presentan dependencias como sesiones (requieren inicio de sesión), validación de firmas digitales (microservicios firmados), datos dinámicos variables (IDs de usuario, direcciones, órdenes de trabajo, marcas de tiempo) y, crucialmente, resultados asíncronos que solo devuelven un event_key. En entornos de prueba, el procesamiento de pedidos puede ser lento, requiriendo sondeo prolongado.

Postman permite scripts JavaScript en las secciones Pre-request Script y Tests, accesibles a nivel de Collection o Folder. Esto proporciona funcionalidades similares a setup y teardown, permitiendo preparación, aserciones y limpieza dentro de diferentes alcances.

Capacidades del Sandbox de JavaScript en Postman

  • Lodash: Biblioteca de utilidades para arreglos, objetos y cadenas.
  • Cheerio: Núcleo de jQuery para análisis y manipulación de HTML/XML.
  • tv4: Validador de esquema JSON para verificar la estructura de la respuesta.
  • CryptoJS: Biblioteca criptográfica para AES, DES, HMAC, MD5, SHA1, etc.
  • xml2json / json2xml: Conversión entre formatos XML y JSON.

Los scripts pueden acceder y manipular variables (de entorno, globales), inspeccionar los objetos de solicitud (request) y respuesta (response), y lo más importante, pueden enviar solicitudes HTTP adicionales para manejar dependencias y validaciones.

Generación de Firma Digital

Principio: Insertar un parámetro {{sign}} en la solicitud. El script Pre-request calcula la firma, la establece como variable de entorno, y luego se envía la solicitud.

Los parámetros se parametrizan. La variable de entorno appsecret se usa en el script de cifrado. El script de ejemplo implementa un algoritmo de firma personalizado (ver documentación de la API delUser para la lógica específica).

// Función para concatenar parámetros ordenados recursivamente
function build_sorted_string(param_set) {
    if (typeof param_set === 'string') {
        return param_set;
    }
    const ordered_keys = Object.keys(param_set).sort();
    let query_parts = [];
    for (const key of ordered_keys) {
        const value = build_sorted_string(param_set[key]);
        query_parts.push(`${key}=${value}`);
    }
    return query_parts.join('&');
}

// Calcula la firma MD5 combinando los parámetros ordenados y el appsecret
function generate_signature(secret, data_params) {
    const sorted_query = build_sorted_string(data_params);
    const hash_input = `${sorted_query}appsecret=${secret}`;
    return CryptoJS.MD5(hash_input).toString();
}

// Ejecución principal
const app_secret = pm.environment.get('appsecret');
const request_body = JSON.parse(request.data);
delete request_body.sign; // Excluir el campo sign del cálculo
const calculated_sign = generate_signature(app_secret, request_body);
pm.environment.set('sign', calculated_sign); // Almacenar firma para el request

Gestión de Sesioens y Dependencias entre APIs

Dependencia de Sesión (Login): En el Pre-request Script de la API protegida, se envía una solicitud de inicio de sesión. Postman mantendrá la sesión (cookies) para la solicitud subsiguiente.

// Obtener la URL base del entorno
const service_url = pm.environment.get('base_url');

// Definir el objeto de solicitud para el login (POST form-urlencoded)
const authentication_request = {
    url: `${service_url}/api/user/login/`,
    method: 'POST',
    header: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: {
        mode: 'urlencoded',
        urlencoded: [
            { key: 'name', value: 'testuser' },
            { key: 'password', value: 'securePass123' }
        ]
    }
};

// Enviar la solicitud de login
pm.sendRequest(authentication_request, (error, response) => {
    if (error) {
        console.log('Login failed:', error);
    } else {
        console.log('Login response status:', response.code);
    }
});

Dependencia de Datos (Obtener Token): Para una API que requiere un token dinámico, se añade el parámetro {{token}}. El Pre-request Script solicita el token a otra API y lo almacena en una variable de entorno.

// Recuperar configuración del entorno
const app_id = pm.environment.get('appid');
const base_endpoint = pm.environment.get('base_url');
const token_endpoint = `${base_endpoint}/api/user/getToken/?appid=${app_id}`;

// Realizar la solicitud para obtener el token
pm.sendRequest(token_endpoint, (error, result) => {
    if (error) {
        console.error('Token retrieval error:', error);
    } else {
        // Asumiendo que el token es la parte después del '=' en la respuesta
        const token_value = result.text().split('=')[1];
        pm.environment.set('token', token_value);
    }
});

Sondeo de Resultados en APIs Asíncronas

Principio: La API asíncrona devuelve un event_key. En la sección Tests, se utiliza setInterval en JavaScript para sondear periódicamente un endpoint de estado hasta obtener un resultado final.

// Extraer la clave de evento de la respuesta inicial
const polling_key = pm.response.json().data.event_key;
const admin_base = pm.environment.get('admin');

// Definir la solicitud de consulta de estado
const status_check_request = {
    url: `${admin_base}/customer/COrder/getOrderResult`,
    method: 'POST',
    header: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: {
        mode: 'urlencoded',
        urlencoded: [
            { key: 'event_key', value: polling_key }
        ]
    }
};

let attempt_count = 0;
const MAX_ATTEMPTS = 20;
const POLL_INTERVAL_MS = 3000;

// Función que se ejecuta periódicamente
function pollForResult() {
    pm.sendRequest(status_check_request, (err, res) => {
        attempt_count++;
        if (err) {
            console.log('Polling error:', err);
        } else {
            const result_msg = res.json().data.msg;
            if (result_msg === 'finish' || attempt_count >= MAX_ATTEMPTS) {
                clearInterval(polling_timer);
                console.log(`Polling stopped. Status: ${result_msg}, Attempts: ${attempt_count}`);
            }
        }
    });
}

// Iniciar el sondeo
const polling_timer = setInterval(pollForResult, POLL_INTERVAL_MS);

Etiquetas: Postman JavaScript API testing Pre-request Script Digital Signature

Publicado el 7-27 17:13