TL;DR
- API testing verifica que servicios backend funcionan correctamente sin UI — más rápido y confiable que tests E2E
- Testea: status codes, cuerpo de respuesta, headers, manejo de errores, autenticación, performance
- Herramientas: Postman (manual/aprendizaje), REST Assured (Java), Supertest (Node.js), requests (Python)
- Automatiza en CI/CD — APIs cambian frecuentemente, atrapa breaking changes temprano
- Cubre happy path y escenarios de error (400s, 401, 404, 500)
Ideal para: Backend developers, ingenieros QA, cualquiera testeando microservicios Omite si: Solo necesitas testear sitios estáticos o frontends simples Tiempo de lectura: 18 minutos
Tus tests de frontend pasan. Los usuarios reportan que la app está rota. La API cambió, y nadie testeó el contrato.
API testing atrapa estos problemas antes de que lleguen a usuarios. Es más rápido que UI testing, más confiable, y testea la lógica de negocio real de la que depende tu aplicación.
Este tutorial enseña API testing desde cero — básicos de HTTP, convenciones REST, autenticación, manejo de errores y automatización con herramientas populares.
¿Qué es API Testing?
API (Application Programming Interface) testing verifica que tus servicios backend funcionan correctamente. En lugar de hacer clic en un UI, envías requests HTTP directamente a endpoints y verificas respuestas.
Qué cubre API testing:
- Funcionalidad — ¿hace el endpoint lo que debería?
- Validación de datos — ¿están las respuestas estructuradas correctamente?
- Manejo de errores — ¿falla gracefully?
- Autenticación — ¿está el acceso controlado apropiadamente?
- Performance — ¿puede manejar carga?
Por qué importa API testing:
- Más rápido que UI tests — sin renderizado de browser, milisegundos vs segundos
- Más estable — sin selectores flaky o problemas de timing
- Feedback más temprano — testea antes de que exista el frontend
- Mejor cobertura — testea edge cases imposibles via UI
Fundamentos HTTP
Antes de testear APIs, entiende los básicos de HTTP.
Métodos HTTP
GET /users # Obtener todos los usuarios
GET /users/123 # Obtener usuario 123
POST /users # Crear nuevo usuario
PUT /users/123 # Reemplazar usuario 123
PATCH /users/123 # Actualizar partes de usuario 123
DELETE /users/123 # Eliminar usuario 123
| Método | Propósito | Tiene Body | Idempotente |
|---|---|---|---|
| GET | Leer datos | No | Sí |
| POST | Crear recurso | Sí | No |
| PUT | Reemplazar recurso | Sí | Sí |
| PATCH | Actualización parcial | Sí | No |
| DELETE | Eliminar recurso | Opcional | Sí |
Códigos de Estado
2xx Éxito
├── 200 OK # Request exitoso
├── 201 Created # Recurso creado
├── 204 No Content # Éxito, nada que retornar
4xx Errores de Cliente
├── 400 Bad Request # Input inválido
├── 401 Unauthorized # Auth faltante/inválido
├── 403 Forbidden # Auth válido, sin permiso
├── 404 Not Found # Recurso no existe
├── 409 Conflict # Conflicta con estado actual
├── 422 Unprocessable # Validación falló
5xx Errores de Servidor
├── 500 Internal Error # Bug del servidor
├── 502 Bad Gateway # Error upstream
├── 503 Unavailable # Servidor sobrecargado/mantenimiento
Testing con Postman
Postman es la forma más fácil de empezar con API testing.
Primer Request
- Abre Postman
- Ingresa URL:
https://jsonplaceholder.typicode.com/posts/1 - Método: GET
- Click en Send
Agregando Tests
En Postman, agrega tests JavaScript en la pestaña “Tests”:
// Verificación de status code
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Tiempo de respuesta
pm.test("Response time is less than 500ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});
// Validación de body
pm.test("Has correct structure", function () {
const json = pm.response.json();
pm.expect(json).to.have.property("id");
pm.expect(json).to.have.property("title");
pm.expect(json.id).to.eql(1);
});
// Verificación de header
pm.test("Content-Type is JSON", function () {
pm.expect(pm.response.headers.get("Content-Type"))
.to.include("application/json");
});
REST API Testing con Código
Python con requests
import requests
import pytest
BASE_URL = "https://api.example.com"
class TestUsersAPI:
def test_get_users_returns_list(self):
response = requests.get(f"{BASE_URL}/users")
assert response.status_code == 200
assert isinstance(response.json(), list)
def test_create_user(self):
payload = {
"name": "John Doe",
"email": "john@example.com"
}
response = requests.post(
f"{BASE_URL}/users",
json=payload,
headers={"Content-Type": "application/json"}
)
assert response.status_code == 201
data = response.json()
assert data["name"] == payload["name"]
assert "id" in data
def test_get_nonexistent_user(self):
response = requests.get(f"{BASE_URL}/users/99999")
assert response.status_code == 404
def test_create_user_invalid_email(self):
payload = {"name": "John", "email": "not-an-email"}
response = requests.post(f"{BASE_URL}/users", json=payload)
assert response.status_code == 400
JavaScript con Supertest
const request = require('supertest');
const app = require('../src/app');
describe('Users API', () => {
test('GET /users returns list of users', async () => {
const response = await request(app)
.get('/users')
.expect(200)
.expect('Content-Type', /json/);
expect(Array.isArray(response.body)).toBe(true);
});
test('POST /users creates new user', async () => {
const newUser = {
name: 'John Doe',
email: 'john@example.com'
};
const response = await request(app)
.post('/users')
.send(newUser)
.expect(201);
expect(response.body).toMatchObject(newUser);
expect(response.body.id).toBeDefined();
});
});
Java con REST Assured
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.*;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class UsersApiTest {
@BeforeAll
public static void setup() {
RestAssured.baseURI = "https://api.example.com";
}
@Test
public void getUsersReturnsList() {
given()
.when()
.get("/users")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
}
@Test
public void createUserReturnsCreated() {
String requestBody = """
{
"name": "John Doe",
"email": "john@example.com"
}
""";
given()
.contentType(ContentType.JSON)
.body(requestBody)
.when()
.post("/users")
.then()
.statusCode(201)
.body("name", equalTo("John Doe"))
.body("id", notNullValue());
}
}
Testing de Autenticación
Bearer Token (JWT)
# Paso 1: Login para obtener token
login_response = requests.post(
"https://api.example.com/auth/login",
json={"email": "user@example.com", "password": "secret"}
)
token = login_response.json()["token"]
# Paso 2: Usar token en requests
response = requests.get(
"https://api.example.com/protected",
headers={"Authorization": f"Bearer {token}"}
)
Testing de Escenarios de Auth
class TestAuthentication:
def test_protected_endpoint_requires_auth(self):
response = requests.get(f"{BASE_URL}/protected")
assert response.status_code == 401
def test_invalid_token_rejected(self):
response = requests.get(
f"{BASE_URL}/protected",
headers={"Authorization": "Bearer invalid_token"}
)
assert response.status_code == 401
def test_valid_token_grants_access(self):
token = get_valid_token()
response = requests.get(
f"{BASE_URL}/protected",
headers={"Authorization": f"Bearer {token}"}
)
assert response.status_code == 200
Testing GraphQL
GraphQL usa un único endpoint con queries y mutations.
Testing de Query
def test_graphql_query():
query = """
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
"""
response = requests.post(
f"{BASE_URL}/graphql",
json={
"query": query,
"variables": {"id": "123"}
}
)
assert response.status_code == 200
data = response.json()
assert "errors" not in data
assert data["data"]["user"]["id"] == "123"
Testing de Errores
Testea cómo tu API maneja problemas.
class TestErrorHandling:
def test_malformed_json_returns_400(self):
response = requests.post(
f"{BASE_URL}/users",
data="not valid json",
headers={"Content-Type": "application/json"}
)
assert response.status_code == 400
def test_missing_required_field_returns_400(self):
response = requests.post(
f"{BASE_URL}/users",
json={"name": "John"} # falta email
)
assert response.status_code == 400
def test_duplicate_email_returns_409(self):
# Crear primer usuario
requests.post(f"{BASE_URL}/users", json={
"name": "John", "email": "john@example.com"
})
# Intentar crear duplicado
response = requests.post(f"{BASE_URL}/users", json={
"name": "Jane", "email": "john@example.com"
})
assert response.status_code == 409
Performance Testing
Load Testing con k6
// k6 script: load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 20 }, // Ramp a 20 usuarios
{ duration: '1m', target: 20 }, // Mantener 20 usuarios
{ duration: '10s', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% bajo 500ms
http_req_failed: ['rate<0.01'], // Menos de 1% fallos
},
};
export default function () {
const response = http.get('https://api.example.com/users');
check(response, {
'status is 200': (r) => r.status === 200,
'response time OK': (r) => r.timings.duration < 500,
});
sleep(1);
}
Testing API con Asistencia de IA
Las herramientas de IA pueden acelerar el desarrollo de tests de API.
Lo que la IA hace bien:
- Generar casos de test desde specs OpenAPI/Swagger
- Crear datos de test válidos e inválidos
- Escribir boilerplate para patrones comunes
- Sugerir edge cases para testear
Lo que aún necesita humanos:
- Entender requisitos de negocio
- Diseñar estrategia de testing
- Debuggear tests flaky
- Interpretar resultados de performance
FAQ
¿Qué es el testing de API?
API testing verifica que las APIs funcionan correctamente enviando requests HTTP y validando respuestas. Testea funcionalidad, validación de datos, manejo de errores, autenticación y performance. A diferencia de UI testing, API testing prueba directamente la capa de lógica de negocio.
¿Qué herramientas se usan para API testing?
Herramientas populares incluyen:
- Postman — herramienta GUI para testing manual y automatización
- REST Assured — librería Java para API testing
- Supertest — Node.js/JavaScript API testing
- requests + pytest — Python API testing
- k6 — Performance y load testing
¿Cuál es la diferencia entre API testing y unit testing?
Unit tests verifican funciones individuales aisladas, mockeando todas las dependencias. API tests verifican endpoints HTTP completos, incluyendo routing, middleware, autenticación, operaciones de BD y formateo de respuestas. API tests son tests de integración que verifican que los componentes funcionan juntos.
¿Cómo testeo APIs autenticadas?
- Envía request de login con credenciales
- Extrae token de la respuesta
- Incluye token en header Authorization para requests siguientes
- Guarda token en variable de entorno para reusar
- Implementa refresh de token para tokens que expiran
Recursos Oficiales
Ver También
- Postman Tutorial - Guía completa de API testing con Postman
- REST Assured Guide - Framework Java para API testing
- GraphQL Testing Guide - Testing de APIs GraphQL
- API Performance Testing - Load y stress testing de APIs
- Contract Testing con Pact - Consumer-driven contract testing
