Cómo probar una API web
Una prueba de API envía una petición y comprueba la respuesta. No mira el código que hay detrás. Solo pregunta lo que preguntaría quien llama, y compara la respuesta con lo que la API prometió.
Vas a escribir unas comprobaciones a mano, ver cómo falla una y probar qué pasa cuando una petición se envía dos veces.
Al terminar esta lección
Nota
Puedo probar una API con peticiones buenas, malas y reintentos, y decir qué demuestra cada comprobación.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Caso de prueba | una petición y la respuesta que esperas recibir |
| Estado esperado | el código de estado con que debe responder la API |
| Datos de prueba | filas hechas solo para una prueba, para poder hallarlas y quitarlas |
| Reintento | enviar otra vez la misma petición porque se perdió la primera respuesta |
| Idempotente | enviarla dos veces deja las cosas como tras enviarla una |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una comprobación es una petición y un estado
Escribir curl y leer números a ojo no escala. Escribe la comprobación una vez: un nombre, el estado que quieres y la petición.
Primero da a psql la contraseña y crea la tabla books. Después define en tu terminal una función pequeña llamada check, que envía la petición y dice OK o FALLO.
Da a psql la contraseña
export PGPASSWORD=shopSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Crea la tabla books
psql -h db -U shop -c "drop table if exists books; create table books (id serial primary key, title text not null, year int not null, available boolean not null default true); insert into books (title, year, available) values ('Mapas del mar', 1998, true), ('Rios de Europa', 2004, false), ('Trenes nocturnos', 2011, true); notify pgrst, 'reload schema'"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Define la función check
check() { want=$1; name=$2; shift 2; got=$(curl -s -o /dev/null -w '%{http_code}' "$@"); if [ "$got" = "$want" ]; then echo "OK $name"; else echo "FALLO $name, esperaba $want y llegó $got"; fi; }Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba una petición buena
check 200 "listar libros" "http://api:3000/books"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba algo que debe fallar
check 200 "mal a propósito" "http://api:3000/nothing"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Prueba lo que la API rechaza
La segunda comprobación estaba mal a propósito, para demostrar que la función puede decir FALLO. Una comprobación que siempre dice OK es peor que ninguna.
Un buen conjunto de pruebas dedica tanto tiempo a las peticiones malas como a las buenas. Cada una debe volver como un 4xx con el código correcto, y no debe cambiar los datos.
Comprueba un libro sin título
check 400 "sin título" -X POST -H "Content-Type: application/json" -d '{"year":2019}' "http://api:3000/books"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba un cuerpo que no es JSON
check 400 "json roto" -X POST -H "Content-Type: application/json" -d 'esto no es json' "http://api:3000/books"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba añadir un libro de prueba
check 201 "añadir un libro" -X POST -H "Content-Type: application/json" -d '{"id":900,"title":"Libro de prueba","year":2020}' "http://api:3000/books"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba el mismo id otra vez
check 409 "mismo id otra vez" -X POST -H "Content-Type: application/json" -d '{"id":900,"title":"Libro de prueba","year":2020}' "http://api:3000/books"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba el cuerpo además del estado
curl -s "http://api:3000/books?id=eq.900" | grep -q '"title":"Libro de prueba"' && echo "OK el cuerpo tiene el título" || echo "FALLO el cuerpo tiene el título"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Prueba una petición enviada dos veces
Las redes pierden respuestas, así que los clientes envían otra vez la misma petición. Una petición es idempotente si enviarla dos veces deja los datos como tras enviarla una.
Pruébalo contando filas. Primero un cambio que fija un valor, y luego un POST sin id, que debe crear un libro nuevo cada vez.
Envía el mismo cambio dos veces
for i in 1 2; do curl -s -o /dev/null -w "%{http_code}\n" -X PATCH -H "Content-Type: application/json" -d '{"available":false}' "http://api:3000/books?id=eq.1"; doneSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Envía el mismo libro nuevo dos veces
for i in 1 2; do curl -s -o /dev/null -X POST -H "Content-Type: application/json" -d '{"title":"Dos veces","year":2020}' "http://api:3000/books"; doneSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cuenta los libros llamados Dos veces
psql -h db -U shop -At -c "select count(*) from books where title = 'Dos veces'"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Haz que crear se pueda reintentar
Dos libros llamados Dos veces significan que un reintento creó un duplicado. Quien llama puede elegir el id y hacer segura la creación. Envía el mismo id, con una cabecera que diga "si ya está, actualízalo".
La primera llamada responde 201 y la segunda 200. Las dos dejan una fila.
Envía dos veces una creación segura
for i in 1 2; do curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -H "Prefer: resolution=merge-duplicates" -d '{"id":902,"title":"Una vez","year":2020}' "http://api:3000/books"; doneSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cuenta las filas con ese id
psql -h db -U shop -At -c "select count(*) from books where id = 902"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejemplo resuelto: qué reintentos son seguros
| Petición enviada dos veces | Filas tras la segunda | ¿Reintento seguro? |
|---|---|---|
| PATCH de un libro a available false | Las mismas que tras la primera | Sí, fija un valor |
| POST de un libro sin id | Una fila más que tras la primera | No, crea un duplicado |
| POST con id y merge-duplicates | Las mismas que tras la primera | Sí, el id nombra la fila |
| DELETE del libro 900 | Borrado tras la primera, sigue borrado | Sí, pero el laboratorio responde 204 las dos veces |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Quita las filas de prueba
psql -h db -U shop -c "delete from books where id >= 900 or title = 'Dos veces'"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente prueba solo la petición buena y nunca ve un fallo. Prueba lo que se rechaza. Limpia también tus filas de prueba. Si no, la segunda ejecución encuentra los datos que dejó la primera y falla por algo que no tiene que ver con la API.