Bienvenido al Workshop de API Testing. Durante el taller exploraremos los conocimientos necesarios para construir pruebas automaticas de API usando Axios, Mocha y Chai. Durante el taller exploraremos la configuración de un proyecto desde cero, prepararlo para un proceso de integración continua por medio de Github Actions e interactuar con diferentes métodos o verbos HTTP. Para el desarrollo del taller usaremos GitHub y GitHub Flow para realizar la entrega de cada ejercicio practico.
Ten en cuenta tener estudiados ciertos conceptos importantes (te dejamos unos enlaces 😎):
- Creación y configuración del repositorio
- Configuración inicial del proyecto
- Primera Prueba de API
- Integración Continua
- Reporte de Pruebas
- Verificación de Código Estático
- Autenticación en GitHub
- Consumiendo Métodos GET
- Consumiendo Métodos PUT
- Consumiendo métodos POST y PATCH
- Consumiendo un DELETE y un recurso inexistente
- Consumiendo HEAD y redireccionando peticiones
- Query parameters
- Validación de Esquemas
- Librería Alterna de Clientes
- Futuros Temas
- Aviso
En esta primera parte se creará un repositorio y se realizaran las configuraciones iniciales, antes de comenzar el workshop.
-
Crear un repositorio en GitHub con el nombre de
workshop-api-testing-js
(previo requisito disponer de una cuenta en GitHub, no seleccione ninguna opcion de inicializacion de repositorio). -
Agregar al repositorio la siguiente descripción:
This is a Workshop about Api Testing in JavaScript
-
Crear localmente una carpeta con el nombre de workshop-api-testing-js y luego sitúese dentro de la carpeta.
-
Crear el archivo .gitignore en la raíz del proyecto, luego ingrese a la página https://www.toptal.com/developers/gitignore y en el campo de texto digite su sistema operativo (ej: windows, osx, macos) y selecciónelo de la lista de autocompletar. Repita este paso para su entorno de desarrollo (ej:vscode, sublime, intellij, jetbrains), también agregue la palabra
node
. Presione el botón "Create" para crear el archivo que contendrá una lista de carpetas y archivos de exclusión y copie su contenido dentro del archivo .gitignore (es muy importante que este archivo quede bien generado, y su sombre sea .gitignore, sin ninguna extension adicional). -
A continuación realice el primer commit y suba los cambios a nuestro repositorio remoto de GitHub, digitando los siguientes comandos en tu consola favorita, cada linea es un comando distinto:
echo "# workshop-api-testing-js" >> README.md git init git add README.md git add .gitignore git commit -m "first commit" git branch -M main SI USAN HTTPS USAR ESTE COMANDO -> git remote add origin https://github.com/<usuario>/workshop-api-testing-js.git SI USAN SSH USAR ESTE COMANDO -> git remote add origin git@github.com:<usuario>/workshop-api-testing-js.git git push -u origin main
-
Proteger la rama
main
para que los pull request requieran revisión de otros desarrolladores y se compruebe el estado de nuestros test ("ok" ✔️ o "fallaron" ❌) antes de hacer un merge a la rama.Ir a Settings > Branches adicionamos una regla dando click en add rule. Escribimos
main
en el campo de branch name pattern. Una vez hecho eso, damos click en las siguientes opciones: -
Dentro del menu colaboradores agregar a:
En esta parte se creará un proyecto node desde 0 y se configurará la primera prueba utilizando mocha.
-
Crear una carpeta en la raíz del proyecto llamada
.github
con un archivo llamadoCODEOWNERS
(sin extensión) con lo siguiente:* @holgiosalos @danielgalvis98 @kliver98 @AlejaGonzalezV @NicolasB2 @manuelq12 @Valeryibarra @veronicatofino
-
Instalar NodeJS en su equipo si no lo tiene instalado (version sugerida
v16.14.0
) -
Ejecutar en una consola
npm init
dentro de la ruta donde se encuentra el repositorio y colocar la siguiente información:Parametro Valor Name [Por Defecto] Version [Por Defecto] Description This is a Workshop about Api Testing in JavaScript Entry Point [Por Defecto] Test Command mocha
Git Repository [Por Defecto] Keywords api-testing, dojo, practice Author [Su nombre] <[Su correo]> ([su github]) License MIT -
Instalar la dependencia de desarrollo mocha, chai
npm install --save-dev mocha chai
-
Crear el archivo
HelloWord.test.js
dentro de una carpeta test y utilizar el siguiente codigo como contenidoconst { assert } = require('chai'); describe('Array', () => { describe('#indexOf()', () => { it('should return -1 when the value is not present', function() { assert.equal(-1, [1,2,3].indexOf(4)); }); }); });
-
Ejecutar el comando
npm test
y comprobar que la prueba pasa de forma satisfactoria -
Crear el archivo LICENSE en la raíz del proyecto con lo especificado en https://en.wikipedia.org/wiki/MIT_License (Tenga en cuanta cambiar el año y el copyright holders)
-
Crear una rama llamada
initial-setup
-
Realizar un
commit
donde incluya los 4 archivos modificados con el mensaje “setup mocha configuration” y subir los cambios al repositorio -
Crear un PR y esperar por la aprobación o comentarios de los revisores
-
Una vez aprobado realizar el merge a main seleccionando la opción “squash and merge”.
En esta sesión, crearemos las primeras pruebas consumiendo de distintas formas servicios API Rest. Utilizaremos una librería cliente llamada axios y otra que contiene un enumerador de los principales códigos de respuesta.
-
Crear una nueva rama a partir de main:
git checkout -b <new-branch>
-
Instalar las dependencia de desarrollo http-status-codes
npm install --save-dev http-status-codes
-
Instalar la dependencia axios. (Tenga en cuenta que esta no es de desarrollo)
npm install --save axios
-
Dentro de la carpeta test crear el archivo
MyFirstApiConsume.test.js
const axios = require('axios'); const { expect } = require('chai'); const { StatusCodes } = require('http-status-codes'); describe('First Api Tests', () => { });
-
Agregar una prueba consumiendo un servicio GET
it('Consume GET Service', async () => { const response = await axios.get('https://httpbin.org/ip'); expect(response.status).to.equal(StatusCodes.OK); expect(response.data).to.have.property('origin'); });
-
Agregar una prueba consumiendo un servicio GET con Query Parameters
it('Consume GET Service with query parameters', async () => { const query = { name: 'John', age: '31', city: 'New York' }; const response = await axios.get('https://httpbin.org/get', { query }); expect(response.status).to.equal(StatusCodes.OK); expect(response.config.query).to.eql(query); });
-
Ejecutar las pruebas.
-
Agregar pruebas consumiendo servicios HEAD, PATCH, PUT, DELETE. Utilice https://httpbin.org/ para encontrar los servicios y la documentación de axios
-
Elimine el archivo
test/HelloWord.test.js
-
Haga commit y push de los cambios, creen un PR y solicite la revisión. Una vez aprobado haga merge con main
En esta sesión se configurará la integración continua con Github Actions, adicionalmente se activará dentro de github una validación que sólo permita realizar merge si la integración continua ha pasado. Y por último se configurará mocha para que haga una espera mucho más grande por la ejecución de las pruebas ya que algunos request pueden tomar más de 2 segundos.
-
Ir a la opción Actions del repositorio
-
Buscar el action de Node.js y darle a configurar, esto lo llevará a editar el action
-
Agregar el siguiente contenido
name: Node.js CI on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Use Node.js 16.x uses: actions/setup-node@v3 with: node-version: 16.x cache: 'npm' - run: npm ci - run: npm run build --if-present - name: Run tests run: npm test
-
Modifique el script de test del package.json agregando al final
-t 5000
-
Cree un PR
-
Verificar que la ejecución del action termine correctamente
-
Ir a la configuración del repositorio y modifique el branch protegido main activando github actions como requerido
-
Solicite revisión del PR
A pesar que mocha nos muestra un reporte por consola, en muchas ocasiones es bueno mostrar un reporte con interfaz gráfica para que los managers o clientes puedan ver los resultados de las pruebas. En esta sesión se configurará un reporte HTML que permite ver los resultados de las pruebas cuando lo ejecutemos localmente
-
Instale la dependencia de desarrollo mochawesome
-
Modificar el script test en el
package.json
de la siguiente forma"test": "mocha -t 5000 --reporter mochawesome --reporter-options reportDir=report,reportFilename=ApiTesting"
-
Agregar las siguientes líneas dentro del .gitignore
## Reports ## report
-
Cree un PR y solicite revisión (Dentro de la descripción del PR debe contener una imagen mostrando el reporte HTML que genero mochawesome), como se muestra en la siguiente imagen
Los analizadores de código estático nos permiten estandarizar como los desarrolladores escriben código. En esta sesión se configurará eslint con las reglas de estilo de código propuesto por AirBnb, cómo podemos ejecutar la validación de código y cómo automáticamente se pueden corregir algunas reglas, adicionalmente si no es posible corregirlo de forma automática como poder corregirla.
-
Instalar las dependencias de desarrollo eslint eslint-config-airbnb-base eslint-plugin-import
-
Crear el archivo .eslintrc.yml en la raíz del proyecto, con el siguiente contenido
env: es6: true node: true mocha: true extends: - eslint:recommended - airbnb-base - plugin:import/errors - plugin:import/warnings rules: "comma-dangle": ["error", "never"]
-
Agregar dentro de scripts del package.json
"lint": "eslint ./test/**/*.js"
-
Modificar el script de test agregandole al inicio
npm run lint &&
-
Ejecute el comando
npm run lint -- --fix
(Esto debe resolverle algunos errores de código estático de forma automática) en caso que todos los errores no se resuelvan investigue en qué consiste el error y resuélvalo -
Envíe un PR con los cambios
En ésta sección se realizarán pruebas al API de Github, en donde se consultarán datos del repositorio que hemos creado y se implementarán mecanismos para trabajar con la autenticación de ésta API.
-
Crear un token de acceso en nuestra cuenta de Github seleccionando (repo, gist, users) y darle acceso público a nuestro repositorios. Recuerde que debe copiar el token ya que no volverá a tener acceso a él. Documentación
-
Dentro de la carpeta test crear el archivo
GithubApi.Authentication.test.js
const { StatusCodes } = require('http-status-codes'); const { expect } = require('chai'); const axios = require('axios'); const urlBase = 'https://api.github.com'; const githubUserName = 'AgileTestingColombia'; const repository = 'workshop-api-testing-js'; describe('Github Api Test', () => { describe('Authentication', () => { it('Via OAuth2 Tokens by Header', async () => { const response = await axios.get(`${urlBase}/repos/${githubUserName}/${repository}`, { headers: { Authorization: `token ${process.env.ACCESS_TOKEN}` } }); expect(response.status).to.equal(StatusCodes.OK); expect(response.data.description).equal('This is a Workshop about Api Testing in JavaScript'); }); }); });
-
Reemplazar el valor de githubUserName por su usuario de Github.
-
Reemplazar el valor de repository por el nombre del repositorio
-
Establecer la variable de entorno ACCESS_TOKEN insertando lo siguiente en la consola con el valor del token de acceso
export ACCESS_TOKEN=token_de_acceso
Este paso es necesario realizarlo cada vez que se inicie el computador. Existen otras opciones para la configuración de variables de entorno como hacerlo a través de un archivo de configuración o usando las variables de ambiente de Windows. De esta manera, la variable de entorno persistirá y no será necesario volver a configurarla
-
Ejecutar las pruebas.
-
Adicionar la prueba para autenticación por parámetros.
it('Via OAuth2 Tokens by parameter', async () => { const response = await axios.get( `${urlBase}/repos/${githubUserName}/${repository}`, { access_token: process.env.ACCESS_TOKEN } ); expect(response.status).to.equal(StatusCodes.OK); expect(response.data.description).equal('This is a Workshop about Api Testing in JavaScript'); });
-
Ir a la configuración del repositorio > secrets > actions
-
Agregar la variable ACCESS_TOKEN como una variable del repositorio con su respectivo valor
-
Editar el archivo de ejecución del CI continuous-integration.yml y agregar la variable en el step de nombre Run tests, de tal modo que quede de la siguiente manera:
- name: Run tests env: ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}} run: npm test
-
Subir los cambios a GitHub, crear un PR y solicitar revisión
En esta sesión se automatizarán algunas pruebas utilizando métodos GET de la api de Github, se descargará un archivo de menor tamaño y otro de mayor tamaño y se comprobará con su MD5
- Crear el archivo
GithubApi.Repositories.test.js
y dentro de él hacer el resto de pasos - Consumir el servicio
https://api.github.com/users/aperdomob
y comprobar el nombre, la compañía y la ubicación del usuario - Obtener la lista de los repositorios por medio de hypermedia, y busque un repositorio con el nombre jasmine-json-report sobre ese repositorio verifique el nombre completo del repositorio, si es privado, y la descripción del repositorio. Utilice el método
find
para encontrar el repositorio que busca https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find - Descargue el repositorio en un zip y compruebe que descargó de forma adecuada. Aproveche la hypermedia de las anteriores respuesta para formar la url de descarga
- Obtenga la lista de archivos del repositorio y encuentre el Archivo README.md compruebe su nombre, path y su sha. Use el método containtSubset de chai-subset
- Por último, descargue el archivo README.md con ayuda del hypermedia y compruebe su md5
En esta sesión seguiremos a un usuario de github, comprobaremos que efectivamente lo seguimos y posteriormente volveremos a seguirlo con el fin de comprobar la idempotencia del método PUT
- Crear el archivo GithubApi.Put.test.js y dentro de él hacer el resto de pasos
- Seguir al usuario aperdomob consumiendo con el método PUT la url https://api.github.com/user/following/aperdomob. Verificar que la consulta devuelve un 204 y que efectivamente el cuerpo venga vacío
- Consulte la lista de usuario y verifique que efectivamente sigue a aperdomob, puede consumir https://api.github.com/user/following
- Vuelva a llamar el endpoint para seguir al usuario aperdomob y verifique la idempotencia del método
En esta sesión crearemos un issue in github con un título, posteriormente modificaremos ese issue agregando un cuerpo
- Crear el archivo GithubApi.Issue.test.js y dentro de este, codificar los cambios necesarios para los pasos siguientes
- Obtendremos el usuario logueado mediante el consumo del del servicio
https://api.github.com/user
y verificaremos que tenga al menos un repositorio público - Obtendremos la lista de todos los repositorios como ya lo habíamos hecho anteriormente. De todos los repositorios seleccionaremos uno cualquiera y agregamos una verificación que el repositorio exista.
- A partir del usuario y el nombre del repositorio construimos la url que nos permita crear un issue que contenga solamente un título mediante un método POST la estructura de la url es
https://api.github.com/repos/${username}/${repositoryName}/issues
. Verificamos que el título corresponda y que el cuerpo no contenga contenido - Modifique el issue agregandole un cuerpo mediante un método PATCH la url usando la url
https://api.github.com/repos/${username}/${repositoryName}/issues/{issueNumber}
verifique que el título no haya cambiado y que contenga el nuevo cuerpo
Se creará un gist posteriormente se verificará que exista. Luego se eliminará ese gist y se comprobará que efectivamente ya no exista.
- Crear el archivo
GithubApi.Gist.test.js
y dentro de dentro de este, codificar los cambios necesarios para los pasos siguientes - Cree un gist con un ejemplo de promesas mediante el método POST y la url
https://api.github.com/gists
. Verifique el código de respuesta, la descripción, si es público y el contenido del archivo. Use el método containtSubset de chai-subset - Consulte el gist creado mediante la url provisionada por hypermedia y compruebe que el recurso si exista
- Elimine el gist mediante la misma url usando el método DELETE
- Consulte nuevamente el gist mediante la url y compruebe que el recurso ya no exista
se consumirá por medio de un HEAD un repositorio el cual fue cambiado de nombre para verificar el redireccionamiento. Posteriormente se consumirá con un GET el repositorio que se renombró con el fin de validar que redireccione de forma adecuada.
- Crear el archivo
GithubApi.Redirect.test.js
y dentro de dentro de este, codificar los cambios necesarios para los pasos siguientes - Consultar con el método
HEAD
la urlhttps://github.com/aperdomob/redirect-test
y comprobar que tenga la redirección a la urlhttps://github.com/aperdomob/new-redirect-test
- Consultar con el método GET la url https://github.com/aperdomob/redirect-test y verificar que redireccione de forma correcta
En esta sesión se enviará query parameters para poder obtener más o menos cantidad de datos en una consulta GET.
- Modificar el archivo
GithubApi.Users.test.js
agregando una prueba de cuantos usuarios trae por defecto. - Agregar una prueba que obtenga 10 usuarios y verificar que efectivamente traiga 10 usuarios.
- Agregar una prueba que obtenga 100 usuarios y verificar que efectivamente traiga 100 usuarios.
En muchas ocasiones debemos verificar que la respuesta que entrega debe cumplir con un esquema generalmente ese tipo de pruebas llevan el nombre de “pruebas de contrato”, una forma sencilla de verificarlo es por medio de json schema validator. Lo que se realizará en este ejercicio es automatizar un solo caso de prueba verificando ese esquema
-
Cree el archivo GithubApi.Contract.test.js con el siguiente contenido
const axios = require('axios'); const chai = require('chai'); const { listPublicEventsSchema } = require('./schema/ListPublicEvents.schema'); const { expect } = chai; chai.use(require('chai-json-schema')); const urlBase = 'https://api.github.com'; describe('Given event Github API resources', () => { describe('When wanna verify the List public events', () => { let response; before(async () => { response = await axios.get(`${urlBase}/events`, { headers: { Authorization: `token ${process.env.ACCESS_TOKEN}` } }); }); it('then the body should have a schema', () => expect(response).to.be.jsonSchema(listPublicEventsSchema)); }); });
-
Cree el archivo
schema/ListPublicEvents.schema.js
(En este archivo se agregará el esquema que se validará). Con la siguiente informaciónconst listPublicEventsSchema = { }; exports.listPublicEventsSchema = listPublicEventsSchema;
-
Completar el archivo ListPublicEvents con el esquema que cubra cada una de los keys del json de respuesta, tenga en cuenta tipos de datos (numeros, booleanos, arrays, string, objects), enumeraciones
Existen otras librerías alternas para consumir url en javascript un de esas es isomophic-fetch, para esta sesión se automatizará nuevamente los casos de prueba de la sesión “Consumiendo un DELETE y un recurso inexistente” pero con otra librería.
- Instalar la dependencia
isomorphic-fetch
- Crear el archivo GithubApi.Gist.Fetch.test.js
- Implementar los mismos test cases de la sesión “Consumiendo un DELETE y un recurso inexistente” usando isomorphic-fetch
- Subir archivos
Workshop ideado y creado por @aperdomob @luisbolanoss @yesid-lopez @AlejaGonzalezV