diff --git a/README.md b/README.md index 162cee9..a856d54 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# dede_0 +# asw2122_0 -[![Actions Status](https://github.com/arquisoft/dede_0/workflows/CI%20for%20ASW2122/badge.svg)](https://github.com/arquisoft/dede_0/actions) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Arquisoft_dede_0&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Arquisoft_dede_0) -[![codecov](https://codecov.io/gh/arquisoft/dede_0/branch/master/graph/badge.svg?token=VN4XG9NTRO)](https://codecov.io/gh/pglez82/asw2122_0) +[![Actions Status](https://github.com/pglez82/asw2122_0/workflows/CI%20for%20ASW2122/badge.svg)](https://github.com/pglez82/asw2122_0/actions) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pglez82_asw2122_0&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=pglez82_asw2122_0) +[![codecov](https://codecov.io/gh/pglez82/asw2122_0/branch/master/graph/badge.svg?token=VN4XG9NTRO)](https://codecov.io/gh/pglez82/asw2122_0)

@@ -10,42 +10,43 @@

+Este proyecto es un ejemplo basico de un sitio web utilizando **React** con **Typescript** y un endpoint usando **NodeJS** con **express** -This project is a basic example of website using **React** with **Typescript** and an endpoint using **NodeJS** with **express**. +## Guia de inicio rápido -## Quick start guide -In case you already have node.js and npm, make sure you update them before attempting to build the images +Si tienes instalados node.js y npm, asegurate de actualizarlos antes de intentar construir las imagenes + +Si quieres ejecutar el proyecto necesitarás [git](https://git-scm.com/downloads), [Node.js and npm](https://www.npmjs.com/get-npm) y [Docker](https://docs.docker.com/get-docker/). Asegurate de tenerlos instalados en tu equipo. Descarga el proyecto con `git clone https://github.com/pglez82/asw2122_0`. La manera más rápìda de ejecutar todo es con Docker. -If you want to execute the project you will need [git](https://git-scm.com/downloads), [Node.js and npm](https://www.npmjs.com/get-npm) and [Docker](https://docs.docker.com/get-docker/). Make sure the three of them are installed in your system. Download the project with `git clone https://github.com/arquisoft/dede_0`. The fastest way to launch everything is with docker: ```bash docker-compose up --build ``` -This will create two docker images as they don't exist in your system (the webapp and the restapi) and launch a mongo container database. It will also launch Prometheus and Grafana containers to monitor the webservice. You should be able to access everything from here: +Este comando creará dos imagenes de docker si no existen en tu equipo (la webapp y la restapi) y lanzará un contenedor de mongoDB. Además lanzará contenedores de Prometheus y Grafana para monitorizar el servicio web. Deberias ser capaz de acceder a todo desde aqui: + - [Webapp - http://localhost:3000](http://localhost:3000) - - [RestApi example call - http://localhost:5000/api/users/list](http://localhost:5000/api/users/list) - - [RestApi raw metrics - http://localhost:5000/metrics](http://localhost:5000/metrics) - - [Prometheus server - http://localhost:9090](http://localhost:9090) - - [Grafana server http://localhost:9091](http://localhost:9091) + - [Ejemplo llamada a RestApi - http://localhost:5000/api/users/list](http://localhost:5000/api/users/list) + - [Metricas RestApi - http://localhost:5000/metrics](http://localhost:5000/metrics) + - [Servidor Prometheus - http://localhost:9090](http://localhost:9090) + - [Servidor Grafana http://localhost:9091](http://localhost:9091) -If you want to run it without docker. Compile and run the restapi: +Si quieres ejecutar el proyecto sin Docker primero complila y ejecuta la restapi: + ```shell cd restapi npm install npm start ``` - -Now the webapp: - +a continuación la webapp: ```shell cd webapp npm install npm start ``` -You should be able to access the application in [http://localhost:3000](http://localhost:3000). +Deberias ser capaz de acceder a la aplicación en [http://localhost:3000](http://localhost:3000). -## More information -You can get more information about the respository in the other README files: -- Documentation: https://github.com/arquisoft/dede_0/tree/master/docs -- Webapp: https://github.com/arquisoft/dede_0/tree/master/webapp -- Restapi: https://github.com/arquisoft/dede_0/tree/master/restapi +## Mas información +Encontrarás más información sobre el repositorio en los otros archivos README: +- Documentación: https://github.com/pglez82/asw2122_0/tree/master/docs +- Webapp: https://github.com/pglez82/asw2122_0/tree/master/webapp +- Restapi: https://github.com/pglez82/asw2122_0/tree/master/restapi diff --git a/README_es.md b/README_es.md deleted file mode 100644 index a856d54..0000000 --- a/README_es.md +++ /dev/null @@ -1,52 +0,0 @@ -# asw2122_0 - -[![Actions Status](https://github.com/pglez82/asw2122_0/workflows/CI%20for%20ASW2122/badge.svg)](https://github.com/pglez82/asw2122_0/actions) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pglez82_asw2122_0&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=pglez82_asw2122_0) -[![codecov](https://codecov.io/gh/pglez82/asw2122_0/branch/master/graph/badge.svg?token=VN4XG9NTRO)](https://codecov.io/gh/pglez82/asw2122_0) - -

- - - -

- -Este proyecto es un ejemplo basico de un sitio web utilizando **React** con **Typescript** y un endpoint usando **NodeJS** con **express** - -## Guia de inicio rápido - -Si tienes instalados node.js y npm, asegurate de actualizarlos antes de intentar construir las imagenes - -Si quieres ejecutar el proyecto necesitarás [git](https://git-scm.com/downloads), [Node.js and npm](https://www.npmjs.com/get-npm) y [Docker](https://docs.docker.com/get-docker/). Asegurate de tenerlos instalados en tu equipo. Descarga el proyecto con `git clone https://github.com/pglez82/asw2122_0`. La manera más rápìda de ejecutar todo es con Docker. - -```bash -docker-compose up --build -``` -Este comando creará dos imagenes de docker si no existen en tu equipo (la webapp y la restapi) y lanzará un contenedor de mongoDB. Además lanzará contenedores de Prometheus y Grafana para monitorizar el servicio web. Deberias ser capaz de acceder a todo desde aqui: - - - [Webapp - http://localhost:3000](http://localhost:3000) - - [Ejemplo llamada a RestApi - http://localhost:5000/api/users/list](http://localhost:5000/api/users/list) - - [Metricas RestApi - http://localhost:5000/metrics](http://localhost:5000/metrics) - - [Servidor Prometheus - http://localhost:9090](http://localhost:9090) - - [Servidor Grafana http://localhost:9091](http://localhost:9091) - -Si quieres ejecutar el proyecto sin Docker primero complila y ejecuta la restapi: - -```shell -cd restapi -npm install -npm start -``` -a continuación la webapp: -```shell -cd webapp -npm install -npm start -``` - -Deberias ser capaz de acceder a la aplicación en [http://localhost:3000](http://localhost:3000). - -## Mas información -Encontrarás más información sobre el repositorio en los otros archivos README: -- Documentación: https://github.com/pglez82/asw2122_0/tree/master/docs -- Webapp: https://github.com/pglez82/asw2122_0/tree/master/webapp -- Restapi: https://github.com/pglez82/asw2122_0/tree/master/restapi diff --git a/docs/README.md b/docs/README.md index 39fb722..e30f5e9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,35 +1,37 @@ -## The documentation -In this project the documentation is compiled locally and deployed to GitHub pages. -The deployment url is: [https://pglez82.github.io/asw2122_0/](https://pglez82.github.io/asw2122_0/). +## Documentación +La documentación de este proyecto se compila localmente y se despliega en GitHub pages. +la url en la que se despliega es: [https://arquisoft.github.io/dede_0/](https://arquisoft.github.io/dede_0/). -### Documentation build -For the documentation we are going to use [AsciiDoc](https://asciidoc.org/) and [PlantUML](https://plantuml.com) and follows the [Arc42](https://github.com/arc42/arc42-template) template. If you want to be able to generate the doc locally you need to install Ruby, Java and some dependencies to translate the asciidoc code into html. If you are in Linux you can install Ruby and Java simply by executing: +### Build Documentación +For the documentation we are going to use [AsciiDoc](https://asciidoc.org/) and [PlantUML](https://plantuml.com) and follows the [Arc42](https://github.com/arc42/arc42-template) template. If you want to be able to generate the doc locally you need to install Ruby and some dependencies to translate the asciidoc code into html: + +Para la documentación vamos a utilizar [AsciiDoc](https://asciidoc.org/) y [PlantUML](https://plantuml.com). Seguiremos la plantilla [Arc42](https://github.com/arc42/arc42-template). Si quieres general la documentación en tu ordenador, necesitas instalar Ruby, Java y algunas dependencias para traducir el asciidoc en código html. Si estás en una máquina Linux puedes instalar Java y Ruby simplemente ejecutando: ```shell apt-get install ruby openjdk-8-jre ``` -On Windows you can use [these instructions](https://www.ruby-lang.org/en/documentation/installation). Probably you will have Java already installed in your system, if not, you can download it [here](https://www.oracle.com/es/java/technologies/javase/javase8-archive-downloads.html) +En Windows puedes seguir [estas instrucciones](https://www.ruby-lang.org/en/documentation/installation) para instalar Ruby. Probablemente tengas un JRE de Java instalado, sino puedes descargarlo [aquí](https://www.oracle.com/es/java/technologies/javase/javase8-archive-downloads.html): -Once Ruby is working you can install some gems with `asciidoctor` and `asciidoctor-diagram`. +Una vez que Ruby está instalado y funcionando podemos instalar `asciidoctor` y `asciidoctor-diagram`. ```shell gem install asciidoctor asciidoctor-diagram ``` -Now it is turn to install some dependencies in the `package.json` file inside the `docs` directory: +Ahora solo nos queda instalar las dependencias del `package.json` dentro del directorio `docs`: ```shell cd docs npm install ``` -After installing these tools we can generate the documentation. +Después de instalar todas estas herramientas ya deberíamos de ser capaces de generar la documentación: ```shell npm run build ``` -The documentation will be generated under the `docs/build` directory. +La documentación se generará en el directorio `docs/build`. -### Documentation deployment -If we want to deploy it to GitHub pages, so it is accesible via [https://pglez82.github.io/asw2122_0/](https://pglez82.github.io/asw2122_0/) we need to execute `npm run deploy`. +### Despliegue Documentación +Si queremos desplegar la documentación en GitHub pages, estará accesible en [https://arquisoft.github.io/dede_0/](https://arquisoft.github.io/dede_0/) necesitamos ejecutar `npm run deploy`. -If you check the `package.json` in this directory you can see how deploying is as easy as executing `gh-pages -d build`, which can be directly executed using `npm run deploy` in the docs directory. The `gh-pages` package is in charge of pushing the documentation generated directory (basically some htmls) to a special github branch called gh-pages. Everything pushed to this branch is accessible in the repository page. Note that we only want to push there the documentation. Also is important that the documentation build is not pushed to the other branches of the project. \ No newline at end of file +Si revisas el `package.json` de este directorio veras como desplegar es tan facil como ejecutar `gh-pages -d build`, que puede hacerse ejecutando directamente `npm run deploy` en el directorio de la doumentación. el paquete `gh-pages` se encarga de subir la documentación generada (basicamente archivo html) a una rama especial de github llamda gh-pages. Todo lo que se suba a esa rama es acesible en la página del repositorio. Ten en cuenta que solo queremos subir ahí la documentación. También es importante que el build de la documentación no se suba a otras ramas del proyecto. \ No newline at end of file diff --git a/docs/README_es.md b/docs/README_es.md deleted file mode 100644 index e30f5e9..0000000 --- a/docs/README_es.md +++ /dev/null @@ -1,37 +0,0 @@ -## Documentación -La documentación de este proyecto se compila localmente y se despliega en GitHub pages. -la url en la que se despliega es: [https://arquisoft.github.io/dede_0/](https://arquisoft.github.io/dede_0/). - -### Build Documentación -For the documentation we are going to use [AsciiDoc](https://asciidoc.org/) and [PlantUML](https://plantuml.com) and follows the [Arc42](https://github.com/arc42/arc42-template) template. If you want to be able to generate the doc locally you need to install Ruby and some dependencies to translate the asciidoc code into html: - -Para la documentación vamos a utilizar [AsciiDoc](https://asciidoc.org/) y [PlantUML](https://plantuml.com). Seguiremos la plantilla [Arc42](https://github.com/arc42/arc42-template). Si quieres general la documentación en tu ordenador, necesitas instalar Ruby, Java y algunas dependencias para traducir el asciidoc en código html. Si estás en una máquina Linux puedes instalar Java y Ruby simplemente ejecutando: - -```shell -apt-get install ruby openjdk-8-jre -``` - -En Windows puedes seguir [estas instrucciones](https://www.ruby-lang.org/en/documentation/installation) para instalar Ruby. Probablemente tengas un JRE de Java instalado, sino puedes descargarlo [aquí](https://www.oracle.com/es/java/technologies/javase/javase8-archive-downloads.html): - -Una vez que Ruby está instalado y funcionando podemos instalar `asciidoctor` y `asciidoctor-diagram`. - -```shell -gem install asciidoctor asciidoctor-diagram -``` - -Ahora solo nos queda instalar las dependencias del `package.json` dentro del directorio `docs`: - -```shell -cd docs -npm install -``` -Después de instalar todas estas herramientas ya deberíamos de ser capaces de generar la documentación: -```shell -npm run build -``` -La documentación se generará en el directorio `docs/build`. - -### Despliegue Documentación -Si queremos desplegar la documentación en GitHub pages, estará accesible en [https://arquisoft.github.io/dede_0/](https://arquisoft.github.io/dede_0/) necesitamos ejecutar `npm run deploy`. - -Si revisas el `package.json` de este directorio veras como desplegar es tan facil como ejecutar `gh-pages -d build`, que puede hacerse ejecutando directamente `npm run deploy` en el directorio de la doumentación. el paquete `gh-pages` se encarga de subir la documentación generada (basicamente archivo html) a una rama especial de github llamda gh-pages. Todo lo que se suba a esa rama es acesible en la página del repositorio. Ten en cuenta que solo queremos subir ahí la documentación. También es importante que el build de la documentación no se suba a otras ramas del proyecto. \ No newline at end of file diff --git a/restapi/README.md b/restapi/README.md index 515a0f6..3382872 100644 --- a/restapi/README.md +++ b/restapi/README.md @@ -1,49 +1,51 @@ ## Restapi -The objective for this part is to make a rest API using Express and Node.js using TypeScript. We will implement only two functions, one push petition, for registering a new user and a get petition, to list all the users in the system. The webservice will be deployed using docker. - -Lets analyze the main packages used in this part (file package.json): -- express: this is the main dependency for building the API. Express is a NodeJS web framework very useful for building API endpoints though it has other applications as well. -- cors: Cross-Origin Resource Sharing, is useful for allowing petitions only from certain domains, in this case, we will allow only petitions from localhost. -- express-validator: useful for validate the input of the API calls. This improves security avoiding code injection attacks. -- express-prom-bundle and prom-client: middleware to capture the petitions and send statistics to prometheus. This is useful for monitoring the webservice. -- @types packages. Types for coding using typescript. + +El objetivo de esta parte es crear una al rest APi utilizando Express y Node.js con TypeScript. Solo vamos a implementar dos funciones. Una petición post para registrar un nuevo usuario y una petición get que devolverá un listado de todos los usuarios en el sistema. Es servicio web se desplegará utilizando Docker. + +Vamos a analizar los paquetes principales utilizados en esta parte (archivo package.json): +- express: Es la dependencia principal para la construcción de la API. Express es un framework web de NodeJS muy util para la construcción de endpoints de una API aunque permite otras funcionalidades +- cors: Cross-Origin Resource Sharing, Es util para permitir peticiones solo desde determinados dominios, en este ejemplo,unicamente permitimos peticiones desde el localhost. +- express-validator: Util para la validación de las peticiones de la API. Mejora la seguridad evitando ataques de inyección de código. +- express-prom-bundle y prom-client: Middleware para capturar las peticiones y enviar estadísticas a prometheus. Es muy util para monitorizar nuestro servicio web. +- @types packages. Tipos para programar utilizando Typescript. -The code is quite straight forward, the [server.ts](server.ts) file launchs the api. The [api.ts](api.ts) is actually the api, where you will see there two api entry points, one post for creating a new user, and one get to list all the users. +Este código es bastante sencillo, el archivo [server.ts](server.ts) lanza la API y en el archivo [api.ts](api.ts) donde ESTÁN las 2 peticiones. -For launching the API we can use `npm start`. This will launch the file `server.ts` using the package `ts-node-dev`. This package is useful for launching Typescript files with the additional feature of being able to reload the server if we change the code. +Para lanzar la API podemos ejecutar `npm start`. Este comando lanzará el archivo `server.ts`. El paquete `ts-node-dev` recargará el servidor cada vez que guardemos algún cambio en nuestro código de Typescript. Es muy útil. -### Testing the rest api -For testing we need to do simulate petitions against the API. In this case we are using a tool called [Supertest](https://www.npmjs.com/package/supertest). +### Testeando la rest api +Para testear necesitamos simular peticiones contra la API. Para hacer esto utilizaremos una herramienta llamada [Supertest](https://www.npmjs.com/package/supertest). -Note: These dependencies are save only for dev mode, we do not need them for production. +Ojo: Estas dependencias se guardaran para modo desarrollo, no son necesarias en producción. -The idea is to use Jest (as in the webapp) as the main testing framework. For making the get or post petitions we are going to use supertest. The [api.test.ts](tests/api.test.ts), has the implementation of the tests. The `beforeAll` method is charge of starting the API. +La idea es utilizar Jest (como en la webapp) como framework principal de testing. Para realizar las peticiones GET o POST utilizaremos Supertest. El archivo [api.test.ts](tests/api.test.ts), contiene la implementación de los tests. El método `beforeAll` se carga al iniciar la API. -After configuring the tests in the `package.json` we can run them using `npm run test`. +Tras configurar los tests en el `package.json` podemos ejecutarlos utilizando `npm run test`. -### Docker image for the restapi -In the Dockerfile of this folder we have the command for building an image for the restapi. We just install the dependencies and launch the API using `npm start`. +### Imagen Docker para la restapi +En el Dockerfile de este directorio se encuentran los comandos para construir una imagen de la restapi. Solo tenemos que instalar las dependencias y arrancar la API utilizando `npm start`. -### Monitoring (Prometheus and Grafana) -In this step we are going use [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) to monitor the restapi. First step is modifying the restapi launch to capture profiling data. In nodejs this is very easy. After installing the required packages (express-prom-bundle and prom-client), we need to modify the `restapi/server.js` in order to capture the profiling data adding: +### Monitorización (Prometheus y Grafana) +En esta etapa vamos a utilizar [Prometheus](https://prometheus.io/) y [Grafana](https://grafana.com/) para monitorizar nuestra restapi. El primer paso es modificar el lanzamiento de la restapi para capturar los datos de "profiling". En Nodejs es muy sencillo, tras instalar los paquetes necesarios (express-prom-bundle y prom-client), debemos modificar el `restapi/server.js` para capturar los datos de profiling añadiendo: ```javascript const metricsMiddleware = promBundle({includeMethod: true}); app.use(metricsMiddleware); ``` -Now when we launch the api, in [http://localhost:5000/metrics](http://localhost:5000/metrics) we have a metrics endpoint from which get the profiling data. The idea here is to have another piece of software running (called [Prometheus](https://prometheus.io/)) that will get this data, let say, every five seconds. Then, another software called [Grafana](https://grafana.com/) will display this using beautiful charts. +Ahora cuando lancemos la API en [http://localhost:5000/metrics](http://localhost:5000/metrics) tendremos un endpoint de metricas con datos de desempeño. La idea es tener otra pieza de software corriendo (llamada [Prometheus](https://prometheus.io/)) que cogerá estos datos, digamos, cada cinco segundos. a continuación otro software llamado [Grafana](https://grafana.com/) los mostrará con graficos chulos. -For running Prometheus and Grafana we can use several docker images. Check `docker-compose.yml` to see how these images are launched. +Para lanzar Prometheus y Grafana podemos utilizar diferentes imagenes de Docker. Comprueba `docker-compose.yml` para ver como se lanzan estas imagenes. -Note: in the `prometheus.yml` we are telling prometheus where is our restapi metrics end point. In Grafana `datasources/datasource.yml` we are telling where to find prometheus data. +Ojo: en `prometheus.yml` le estamos indicando a prometheus donde esta el endpoint de metricas de nuesta restapi. En Grafana `datasources/datasource.yml` indicamos donde encontrar los datos de prometheus. -In both configuration files we need to stablish the uris of restapi metrics and the prometheus datasource. Right now they are configured to work using docker-compose network. If you want to use these individual docker commands, you need to change these uris to point to localhost +En ambos archivos de configuración necesitamos establecer las uris de las metricas de la resapi y de la fuente de datos de prometheus. En este momento están configurados para utilizar la red de docker-compose. Si quieres utilizar estos comandos de docker individualmente tienes que cambiar las uris para que apunten al localhost -Once launched all the system is launched (see the Quick Start Guide), we can simulate a few petitions to our webservice: +Una vez lanzado esto todo el sistema está corriendo (ver la guia de inicio rápido). Ahora podemos simular unas cuantas peticiones en nuestro servicio web. ``` sudo apt-get install apache2-utils ab -m GET -n 10000 -c 100 http://localhost:5000/api/users/list ``` -In the Grafana dashboard we can see how the number of petitions increases dramatically after the call. -A good reference with good explanations about monitoring in nodejs can be found [here](https://github.com/coder-society/nodejs-application-monitoring-with-prometheus-and-grafana). +En el cuadro de mando de Grafana podemos ver como aumenta rapidamente el número de peticiones tras llamarla. + +Una buena referencia con explicaciones sobre monitorización en Nodejs puede encontrarse [Aqui](https://github.com/coder-society/nodejs-application-monitoring-with-prometheus-and-grafana). diff --git a/restapi/README_es.md b/restapi/README_es.md deleted file mode 100644 index 3382872..0000000 --- a/restapi/README_es.md +++ /dev/null @@ -1,51 +0,0 @@ -## Restapi - -El objetivo de esta parte es crear una al rest APi utilizando Express y Node.js con TypeScript. Solo vamos a implementar dos funciones. Una petición post para registrar un nuevo usuario y una petición get que devolverá un listado de todos los usuarios en el sistema. Es servicio web se desplegará utilizando Docker. - -Vamos a analizar los paquetes principales utilizados en esta parte (archivo package.json): -- express: Es la dependencia principal para la construcción de la API. Express es un framework web de NodeJS muy util para la construcción de endpoints de una API aunque permite otras funcionalidades -- cors: Cross-Origin Resource Sharing, Es util para permitir peticiones solo desde determinados dominios, en este ejemplo,unicamente permitimos peticiones desde el localhost. -- express-validator: Util para la validación de las peticiones de la API. Mejora la seguridad evitando ataques de inyección de código. -- express-prom-bundle y prom-client: Middleware para capturar las peticiones y enviar estadísticas a prometheus. Es muy util para monitorizar nuestro servicio web. -- @types packages. Tipos para programar utilizando Typescript. - -Este código es bastante sencillo, el archivo [server.ts](server.ts) lanza la API y en el archivo [api.ts](api.ts) donde ESTÁN las 2 peticiones. - -Para lanzar la API podemos ejecutar `npm start`. Este comando lanzará el archivo `server.ts`. El paquete `ts-node-dev` recargará el servidor cada vez que guardemos algún cambio en nuestro código de Typescript. Es muy útil. - -### Testeando la rest api -Para testear necesitamos simular peticiones contra la API. Para hacer esto utilizaremos una herramienta llamada [Supertest](https://www.npmjs.com/package/supertest). - -Ojo: Estas dependencias se guardaran para modo desarrollo, no son necesarias en producción. - -La idea es utilizar Jest (como en la webapp) como framework principal de testing. Para realizar las peticiones GET o POST utilizaremos Supertest. El archivo [api.test.ts](tests/api.test.ts), contiene la implementación de los tests. El método `beforeAll` se carga al iniciar la API. - -Tras configurar los tests en el `package.json` podemos ejecutarlos utilizando `npm run test`. - -### Imagen Docker para la restapi -En el Dockerfile de este directorio se encuentran los comandos para construir una imagen de la restapi. Solo tenemos que instalar las dependencias y arrancar la API utilizando `npm start`. - -### Monitorización (Prometheus y Grafana) -En esta etapa vamos a utilizar [Prometheus](https://prometheus.io/) y [Grafana](https://grafana.com/) para monitorizar nuestra restapi. El primer paso es modificar el lanzamiento de la restapi para capturar los datos de "profiling". En Nodejs es muy sencillo, tras instalar los paquetes necesarios (express-prom-bundle y prom-client), debemos modificar el `restapi/server.js` para capturar los datos de profiling añadiendo: -```javascript -const metricsMiddleware = promBundle({includeMethod: true}); -app.use(metricsMiddleware); -``` -Ahora cuando lancemos la API en [http://localhost:5000/metrics](http://localhost:5000/metrics) tendremos un endpoint de metricas con datos de desempeño. La idea es tener otra pieza de software corriendo (llamada [Prometheus](https://prometheus.io/)) que cogerá estos datos, digamos, cada cinco segundos. a continuación otro software llamado [Grafana](https://grafana.com/) los mostrará con graficos chulos. - -Para lanzar Prometheus y Grafana podemos utilizar diferentes imagenes de Docker. Comprueba `docker-compose.yml` para ver como se lanzan estas imagenes. - -Ojo: en `prometheus.yml` le estamos indicando a prometheus donde esta el endpoint de metricas de nuesta restapi. En Grafana `datasources/datasource.yml` indicamos donde encontrar los datos de prometheus. - -En ambos archivos de configuración necesitamos establecer las uris de las metricas de la resapi y de la fuente de datos de prometheus. En este momento están configurados para utilizar la red de docker-compose. Si quieres utilizar estos comandos de docker individualmente tienes que cambiar las uris para que apunten al localhost - -Una vez lanzado esto todo el sistema está corriendo (ver la guia de inicio rápido). Ahora podemos simular unas cuantas peticiones en nuestro servicio web. - -``` -sudo apt-get install apache2-utils -ab -m GET -n 10000 -c 100 http://localhost:5000/api/users/list -``` - -En el cuadro de mando de Grafana podemos ver como aumenta rapidamente el número de peticiones tras llamarla. - -Una buena referencia con explicaciones sobre monitorización en Nodejs puede encontrarse [Aqui](https://github.com/coder-society/nodejs-application-monitoring-with-prometheus-and-grafana). diff --git a/webapp/README.md b/webapp/README.md index 141fc9c..329352c 100644 --- a/webapp/README.md +++ b/webapp/README.md @@ -1,94 +1,96 @@ -## The webapp -In this case we are using React with Typescript for the webapp. Lets create the app in the directory webapp with the following command (make sure you have npm installed in your system): +## La webapp +Utilizaremos React con Typescript para la webapp. Vamos a crear la app en el directorio webapp con los siguientes comandos (asegurate que npm está instalado en tu sistema:) ```console npx create-react-app my-app --template typescript ``` -At this point we can already run the app with: +En este punto ya podemos correr la app con: ```console cd webapp npm start ``` -The app will launch and it will be listening in port 3000. At this point this app is a Hello World app in React. +La app se lanzará y escuchará en el puerto 3000. Ahora mismo la app es un "Hola Mundo" en React. +Vamos a hacer algunas modificaciones en la app, crearemos una app que pida el nombre y el email al usuario y lo envíe a una api rest.Además la webapp listará todos los usuarios registrados. -Lets make some modifications to the app, we will create an app that asks the name and email to the user and send it to an api rest. The webapp will list all the register users in the site. +Basicamente la app debería ser capaz de coger el nombre y el email del usuario, enviarlo a la api y refrescar la lista de los usuarios desde la api. Puedes revisar el código relevante en los componentes +[EmailForm.tsx](src/components/EmailForm.tsx) y [UserList.tsx](src/components/UserList.tsx). El componente [App.tsx](src/App.tsx) funciona como coordinador de los otros componentes. -Basically the app should be able to get the name and email of a user, send it to the api, and then refresh the list of the users from the api. You can check the relevant code in the components [EmailForm.tsx](src/components/EmailForm.tsx) and [UserList.tsx](src/components/UserList.tsx). The [App.tsx](src/App.tsx) component acts as the coordinator for the other components. +### Testeando la webapp -### Testing the webapp +#### Tests unitarios +Basicamente estos tests se aseguran que cada componente trabaja de manera aislada. Esto es importante para comprobar que se renderizan correctamente. Estos tests se realizan utilizando jest y pueden ejercutarse con `npm run test`. Cada vez que se ejecutan los tests se realiza un analisis de covertura de código. Si se configura apropiadamente este analisis puede ser explotado por herramientas como [CodeCov](https://about.codecov.io/) para crear informes de covertura de código. -#### Unit tests -Basically these tests make sure that each component work isolated. It is important to check that they render properly. These tests are done using jest and you can execute them with `npm run test`. A code coverage analysis is generated every time we run the tests. If properly configured, this can be exploited by tools like [CodeCov](https://about.codecov.io/) to create reports of code coverage. -Some tests needs to mock some parts of the application. For instance, the `EmailForm.tsx` component uses the api for adding a user. In the unitary tests we should mock these calls to make more robusts tests. You can check the file [EmailForm.test.tsx](src/components/EmailForm.test.tsx) to learn how this is done. -For instance: +Algunos tests necesitan simular algunas partes de la aplicación. Por ejemplo el componente `EmailForm.tsx` utiliza la api para añadir un usuario. En los tests unitarios debemos simular estas llamadas para obtener resultados más robustos. Puedes revisar el archivo [EmailForm.test.tsx](src/components/EmailForm.test.tsx) para aprender como se hace esto. +Por ejemplo: ```javascript jest.spyOn(api,'addUser').mockImplementation((user:User):Promise => Promise.resolve(false)) ``` -will mock the implementation of the addUser function. Instead of calling the API, we just return false simulating that the webservice has failed to add a new user. +Simularemos la función addUser. En lugar de llamar a la API, simulamos que el servicio web ha fallado al tratar de añadir un usuario. -### Docker image for the web app -The `Dockerfile` for the webapp is pretty simple. Just copy the app, install the dependencies, build the production version an then run a basic webserver to launch it. +### Imagen Docker para la aplicación web +El `Dockerfile` para la aplicación web es bastante simple. Solo copia la aplicación, instala las dependencias, crea la versión de producción y corre un servidor web básico para lanzarla. -In order to run the app, we need a server. `npm start` is not good for production so we are going to use [Express](https://expressjs.com/es/). Check [server.js](webapp/server.ts) in the webapp to understand the configuration. As we will run it in port 3000 (in localhost), we have to bind this port with the port in our local machine. +Necesitamos un servidor para poder correr la aplicación. No es recomendable ejecutar `npm start` en un entorno de producción por lo que utilizaremos [Express](https://expressjs.com/es/). Revisa [server.js](webapp/server.ts) en el directotio webapp para entender la configuración. Mientras corramos el servicio en el puerto 3000 (en localhost) tendremos que conectar este puerto con el puerto de nuestra máquina local. - -### Launching everything at the same time (docker-compose) -All the containers will be launched in order using docker compose. Check the file [docker-compose.yaml](docker-compose.yaml) to see the definition of the containers and their launch process. Here are the commands to launch the system and to turn it down: +### Lanzar todo al mismo tiempo (docker-compose) +doker compose permite lanzar todos los contenedores en el orden adecuado. Revisa el archivo [docker-compose.yaml](docker-compose.yaml) para ver la definición de los contenedores y sus procesos de lanzamiento. Aqui tienes los comandos para lanzar el sistema y apagarlo: ``` docker-compose up ``` ``` docker-compose down ``` -Note: if you change something in the code you should rebuild the images using the `--build` flag +Nota: Si cambias algo en el código deberás reconstruir las imagenes utilizando la bandera `--build`. -### Continuous integration/Continuous Delivery -In this step we are going to setup GitHub Actions in order to have CI in our system. The idea is that, every time we create a new release, build the system (restapi and webapp), run the tests, and if everything is ok, build the docker images and upload them to Github packages. Then we can deploy the application using these images. +### Integración continua (CI)/Entrega continua (CD) -The workflow for this is in [asw2122.yml](.github/workflow/asw2122.yml). In this file you can see that there are two jobs, one for the restapi, one for the webapp. Jobs are executed in pararel so this will speed up our build. +En esta etapa vamos a configurar GitHub Actions para tener CI en nuestro sistema. La idea es que cada vez que creemos una nuevo entregable (release) se construya el sistema (restapi y webapi), se ejecuten los tests y si todo funciona correctamente se construirán las imagenes de docker y se subirán a GiHub packages. Entonces podremos desplegar nuestra nuestra aplicación utilizando estas imagenes. -So, the first to jobs in this file build the webapp and the restapi (in parallel). If everything goes well, check the e2e tests (later in this document) and if these acceptance tests pass ok, create the docker images and deploy them. +El flujo de trabajo se encuentra en el archivo [asw2122.yml](.github/workflows/asw2122.yml). Si lo revisas podrás ver que existen dos trabajos, uno para la restapi(**unit-test-restapi**) y otro para la webapp(**unit-test-webapp**). Estos trabajos se ejecutan de forma paralela por lo que aceleran la construcción de las imagenes. +Si todo va bien revisarán los tests e2e (end to end) y si estos test de aceptación pasan se crearán las imagenes de docker y se desplegarán. -### E2E testing -Integration tests is maybe the most difficult part to integrate in our system. We have to test the system as a whole. The idea here is to deploy the system and make the tests using [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) (browser automatization) and [jest-cucumber](https://www.npmjs.com/package/jest-cucumber) (user stories). We will also be using [expect-puppeteer](https://www.npmjs.com/package/expect-puppeteer) to make easier the test writing. All the structure needed is under the `webapp/e2e` directory. This tests can be run locally using `npm run test:e2e` and they will be run also in GitHub Actions, just after the unitary tests. +### Testting E2E +Los tests de integración es la parte más dificil de integrar en nuestro sistema. tenemos que testear nuestro sistema como un todo. la idea es desplegar nuestro sistema y hacer tests utilizando [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) (automatización del navegador) and [jest-cucumber](https://www.npmjs.com/package/jest-cucumber) (historias de usuario). También utilizaremos [expect-puppeteer](https://www.npmjs.com/package/expect-puppeteer) para facilitar la escritura de los tests. Todo lo necesario para vertebrar esta estructura se encuentra en el directorio `webapp/e2e`. Estos tests pueden ejecutarse de manera local utilizando el comando `npm run test:e2e` y en GitHub Actions justo después de los tests unitarios. -In this project the E2E testing user stories are defined using Cucumber. Cucumber uses a language called Gherkin to define the user stories. You can find the example in the `features` directory. Then, the actual tests are in the folder `steps`. We are going to configure jest to execute only the tests of this directory (check the `jest.config.ts` file). +En este proyecto las historias de usuario utilizadas por los tests E2E se definen utilizando Cucumber. Cucumber utiliza un lenguaje llamado Gherkin para poder crear estas historias. Puedes encontrar un ejemplo en el directorio `webapp/e2e/features` y los tests reales se encuentran en este directorio `webapp/e2e/steps` (revisa el archivo `jest.config.ts`). -The E2E tests have two extra difficulties. The first one, we need a browser to perform the tests as if the user was using the application. For this matter, we use `jest-peppeteer` that will launch a Chromium instance for running the tests. The browser is started in the `beforeAll` function. Note that the browser is launched in a headless mode. This is neccesary for the tests to run in the CI environment. If you want to debug the tests you can always turn this feature off. The second problem is that we need to run the restapi and the webapp at the same time to be able to run the tests. For achieving this, we are going to use the package `start-server-and-test`. This package, allows us to launch multiple servers and then run the tests. No need for any configuration. We can configure it straight in the `package.json` file: +Los tests E2E tienes dos dificultades añadidas. +- La primera es que necesitamos un navegador que ejecute los tests simulando el comportamiento del usuario utilizando la aplicación. Esa es la razón por la que utilizamos `jest-peppeteer` que lanzará una instancia [Chromium](https://es.wikipedia.org/wiki/Chromium_(navegador)) para correr los tests. El navegador comienza en la función `beforeAll`. Ten en cuenta que el navegador se lanza en "headless mode" (modo sin cabeza: Sin interfaz gráfica) +Esto es necesatio para correr los tests el entorno de integración continua (CI). Si quieres depurar siempre puedes deshabilitar esta característica. +- El segundo problema es que para poder correr estos tests es imprescindible que se estén ejecutando la restapi y la webapp. El paquete `start-server-and-test` nos va a ayudar a lograrlo ya que nos permite lanzar varios servidores a la vez y puede configurarse directamente en el archivo `package.json`: ```json "test:e2e": "start-server-and-test 'npm --prefix ../restapi start' http://localhost:5000/api/users/list prod 3000 'cd e2e && jest'" ``` +El `package.json` acepta pares de parámetos (lanza un servidor y una URl para comprobar que está ejecutandose). Además acepta comandos npm ( para una instancia de la webapp en producción, con `npm run prod`) y el último parámetro lanzará jest para que ejecute los tests E2E. -The package accepts pairs of parameters (launch a server and an URL to check if it is running. It also accepts npm commands (for instance prod, for the webapp, that will run `npm run prod`). The last parameter of the task will be launching jest to run the E2E tests. +### Tests de carga (Gatling) +Esta parte se llevará a cabo utilizando [Gatling](https://gatling.io/). Gatling simulará la carga de datos en nuestro sistema haciendo peticiones a la webapp. -### Load testing (Gatling) -This part will be carried out using [Gatling](https://gatling.io/). Gatling will simulate load in our system making petitions to the webapp. +Para utilizara Gatling para hacer los tests de carga en nuestra aplicación necesitamos [descargarlo](https://gatling.io/open-source/start-testing/). Basicamenre el programa tiene dos partes. Una [grabadora](https://gatling.io/docs/current/http/recorder) que capturará las acciones que queramos testear y un progrma que ejecute estas acciones y que recoja los resultados. Gatling se encargará de capturar todos los tiempos de respuesta de nuestras peticiones de nuestras peticiones y las presentará graficamente en unos gráficos para un análisis posterior. -In order to use Gatling for doing the load tests in our application we need to [download](https://gatling.io/open-source/start-testing/) it. Basically, the program has two parts, a [recorder](https://gatling.io/docs/current/http/recorder) to capture the actions that we want to test and a program to run this actions and get the results. Gatling will take care of capture all the response times in our requests and presenting them in quite useful graphics for its posterior analysis. +Una vez descargado Gatling necesitamos inicializar la [grabadora](https://gatling.io/docs/current/http/recorder). No es más que un proxy que intercepta todas las acciones que se llevan a cabo en nuestro navegador. Eso significa que tenemos que configurar nuestro navegador para que utilize ese proxy siguiendo los siguientes pasos: -Once we have downloaded Gatling we need to start the [recorder](https://gatling.io/docs/current/http/recorder). This works as a proxy that intercepts all the actions that we make in our browser. That means that we have to configure our browser to use a proxy. We have to follow this steps: +1. Configurar la grabadora en **HTTP proxy mode**. +2. Configurar el **modo HTTPs** para "Certificate Authority". +3. Generar un **certificado CA** y una key. Para esto hay que hacer click en el botón "Generate CA" . Tendrás que escoger el directorio para generar los certificados. Se crearán 2 achivos pem. +4. Configurar Firefox para utilizar estos **certificados CA** (Preferences>Certificates, import the generated certificate). +5. Configurar FireFox para utilizar un **proxy** (Preferences>Network configuration). El proxy estará en localhost:8000. +6. Configurar Firefox para que utilice el proxy incluso si la llamada se produce desde una dirección local. Para esto necesitamos configurar la propiedad `network.proxy.allow_hijacking_localhost` a `true` en `about:config`. -1. Configure the recorder in **HTTP proxy mode**. -2. Configure the **HTTPs mode** to Certificate Authority. -3. Generate a **CA certificate** and key. For this, press the Generate CA button. You will have to choose a folder to generate the certificates. Two pem files will be generated. -4. Configure Firefox to use this **CA certificate** (Preferences>Certificates, import the generated certificate). -5. Configure Firefox to use a **proxy** (Preferences>Network configuration). The proxy will be localhost:8000. -6. Configure Firefox so it uses this proxy even if the call is to a local address. In order to do this, we need to set the property `network.proxy.allow_hijacking_localhost` to `true` in `about:config`. +Una vez tengamos la grabadora configurada y la apliación corriendo (en Heroku por ejemplo), podemos comenzar nuestro primer test. Necesitamos especificar un paquete y un nombre de clase para organizar los tests. El paquete será un directorio y el nombre de clase el nombre del test. En mi caso he utilizado `GetUserList`sin nombre de paquete. Despues de presionar "inicio" la grabadora comenzará a capturar las acciones que hagamos en el navegador. En este momento debes llevar a cabo todas las acciones que quieras grabar. En este caso he navegado hasta la página principal de la webapp y he añadido un usuario. Una vez dejemos de grabar, la simulación se almacenará en el directorio `user-files/simulations`. Escrito en lenguaje [Scala](https://www.scala-lang.org/). Si quieres ver el resultado de un test hecho con gatling puedes verlo en `webapp/loadtestexample`. Ten en cuenta que en esta simulación hay una petición post a la restapi. Los datos que se envián en una petitición post, son almacenados por gattling en el directorio `user-files/resources`. -Once we have the recorder configured, and the application running (in Heroku for instance), we can start recording our first test. We must specify a package and class name. This is just for test organization. Package will be a folder and Class name the name of the test. In my case I have used `GetUsersList` without package name. After pressing start the recorder will start capturing our actions in the browser. So here you should perform all the the actions that you want to record. In my case, I opened the main website and added one user. Once we stop recording the simulation will be stored under the `user-files/simulations` directory, written in [Scala](https://www.scala-lang.org/) language. I have copied the generated file under `webapp/loadtestexample` just in case you want to see how a test file in gatling looks like. Note that this simulation included a post petition to the restapi. Post data is stored under a different directory in the gattling installation directory (`user-files/resources`). -We can modify our load test for instance to inject 20 users at the same time: -```scala +Podemos modificar nuestro test de carga ,por ejemplo, inyectando 20 usuarios al mismo tiempo: +``` setUp(scn.inject(constantUsersPerSec(3).during(15))).protocols(httpProtocol) ``` -changing it in the scala file. Check [here](https://gatling.io/docs/gatling/reference/current/core/injection/) to see more options about generating load. -In order to execute the test we have to execute: +cambiarlo en el achivo scala. Revisa [esta página](https://gatling.io/docs/gatling/reference/current/core/injection/) para tener más información sobre como inyectar carga en nuestros tests de carga. -```bash -gatling.sh -s GetUsersList +Para correr los tests necesitmos ejecutar: ``` +gatling.sh -s GetUserList +``` +Se mostrará una vista general de los resultados en la consola, además podremos ver un informe completo en formato wen en el directorio de los resultados. -In the console, we will get an overview of the results and in the results directory we will have the full report in web format. - -It is important to note that we could also dockerize this load tests using this [image](https://hub.docker.com/r/denvazh/gatling). It is just a matter of telling the docker file where your gatling configuration and scala files are and the image will do the rest. +Es importante saber que podedmos dockerizar estos tests de carga utilizando esta [imagen](https://hub.docker.com/r/denvazh/gatling). Tan solo es cuestión de decirle al archivo docker donde se encuentra tu configuración de gatlin y los archivos scala. La imagen hará el resto. diff --git a/webapp/README_es.md b/webapp/README_es.md deleted file mode 100644 index 329352c..0000000 --- a/webapp/README_es.md +++ /dev/null @@ -1,96 +0,0 @@ -## La webapp -Utilizaremos React con Typescript para la webapp. Vamos a crear la app en el directorio webapp con los siguientes comandos (asegurate que npm está instalado en tu sistema:) -```console -npx create-react-app my-app --template typescript -``` -En este punto ya podemos correr la app con: -```console -cd webapp -npm start -``` -La app se lanzará y escuchará en el puerto 3000. Ahora mismo la app es un "Hola Mundo" en React. -Vamos a hacer algunas modificaciones en la app, crearemos una app que pida el nombre y el email al usuario y lo envíe a una api rest.Además la webapp listará todos los usuarios registrados. - -Basicamente la app debería ser capaz de coger el nombre y el email del usuario, enviarlo a la api y refrescar la lista de los usuarios desde la api. Puedes revisar el código relevante en los componentes -[EmailForm.tsx](src/components/EmailForm.tsx) y [UserList.tsx](src/components/UserList.tsx). El componente [App.tsx](src/App.tsx) funciona como coordinador de los otros componentes. - -### Testeando la webapp - -#### Tests unitarios -Basicamente estos tests se aseguran que cada componente trabaja de manera aislada. Esto es importante para comprobar que se renderizan correctamente. Estos tests se realizan utilizando jest y pueden ejercutarse con `npm run test`. Cada vez que se ejecutan los tests se realiza un analisis de covertura de código. Si se configura apropiadamente este analisis puede ser explotado por herramientas como [CodeCov](https://about.codecov.io/) para crear informes de covertura de código. - -Algunos tests necesitan simular algunas partes de la aplicación. Por ejemplo el componente `EmailForm.tsx` utiliza la api para añadir un usuario. En los tests unitarios debemos simular estas llamadas para obtener resultados más robustos. Puedes revisar el archivo [EmailForm.test.tsx](src/components/EmailForm.test.tsx) para aprender como se hace esto. -Por ejemplo: -```javascript -jest.spyOn(api,'addUser').mockImplementation((user:User):Promise => Promise.resolve(false)) -``` -Simularemos la función addUser. En lugar de llamar a la API, simulamos que el servicio web ha fallado al tratar de añadir un usuario. - -### Imagen Docker para la aplicación web -El `Dockerfile` para la aplicación web es bastante simple. Solo copia la aplicación, instala las dependencias, crea la versión de producción y corre un servidor web básico para lanzarla. - -Necesitamos un servidor para poder correr la aplicación. No es recomendable ejecutar `npm start` en un entorno de producción por lo que utilizaremos [Express](https://expressjs.com/es/). Revisa [server.js](webapp/server.ts) en el directotio webapp para entender la configuración. Mientras corramos el servicio en el puerto 3000 (en localhost) tendremos que conectar este puerto con el puerto de nuestra máquina local. - -### Lanzar todo al mismo tiempo (docker-compose) -doker compose permite lanzar todos los contenedores en el orden adecuado. Revisa el archivo [docker-compose.yaml](docker-compose.yaml) para ver la definición de los contenedores y sus procesos de lanzamiento. Aqui tienes los comandos para lanzar el sistema y apagarlo: -``` -docker-compose up -``` -``` -docker-compose down -``` -Nota: Si cambias algo en el código deberás reconstruir las imagenes utilizando la bandera `--build`. - -### Integración continua (CI)/Entrega continua (CD) - -En esta etapa vamos a configurar GitHub Actions para tener CI en nuestro sistema. La idea es que cada vez que creemos una nuevo entregable (release) se construya el sistema (restapi y webapi), se ejecuten los tests y si todo funciona correctamente se construirán las imagenes de docker y se subirán a GiHub packages. Entonces podremos desplegar nuestra nuestra aplicación utilizando estas imagenes. - -El flujo de trabajo se encuentra en el archivo [asw2122.yml](.github/workflows/asw2122.yml). Si lo revisas podrás ver que existen dos trabajos, uno para la restapi(**unit-test-restapi**) y otro para la webapp(**unit-test-webapp**). Estos trabajos se ejecutan de forma paralela por lo que aceleran la construcción de las imagenes. - -Si todo va bien revisarán los tests e2e (end to end) y si estos test de aceptación pasan se crearán las imagenes de docker y se desplegarán. - -### Testting E2E -Los tests de integración es la parte más dificil de integrar en nuestro sistema. tenemos que testear nuestro sistema como un todo. la idea es desplegar nuestro sistema y hacer tests utilizando [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) (automatización del navegador) and [jest-cucumber](https://www.npmjs.com/package/jest-cucumber) (historias de usuario). También utilizaremos [expect-puppeteer](https://www.npmjs.com/package/expect-puppeteer) para facilitar la escritura de los tests. Todo lo necesario para vertebrar esta estructura se encuentra en el directorio `webapp/e2e`. Estos tests pueden ejecutarse de manera local utilizando el comando `npm run test:e2e` y en GitHub Actions justo después de los tests unitarios. - -En este proyecto las historias de usuario utilizadas por los tests E2E se definen utilizando Cucumber. Cucumber utiliza un lenguaje llamado Gherkin para poder crear estas historias. Puedes encontrar un ejemplo en el directorio `webapp/e2e/features` y los tests reales se encuentran en este directorio `webapp/e2e/steps` (revisa el archivo `jest.config.ts`). - -Los tests E2E tienes dos dificultades añadidas. -- La primera es que necesitamos un navegador que ejecute los tests simulando el comportamiento del usuario utilizando la aplicación. Esa es la razón por la que utilizamos `jest-peppeteer` que lanzará una instancia [Chromium](https://es.wikipedia.org/wiki/Chromium_(navegador)) para correr los tests. El navegador comienza en la función `beforeAll`. Ten en cuenta que el navegador se lanza en "headless mode" (modo sin cabeza: Sin interfaz gráfica) -Esto es necesatio para correr los tests el entorno de integración continua (CI). Si quieres depurar siempre puedes deshabilitar esta característica. -- El segundo problema es que para poder correr estos tests es imprescindible que se estén ejecutando la restapi y la webapp. El paquete `start-server-and-test` nos va a ayudar a lograrlo ya que nos permite lanzar varios servidores a la vez y puede configurarse directamente en el archivo `package.json`: - -```json -"test:e2e": "start-server-and-test 'npm --prefix ../restapi start' http://localhost:5000/api/users/list prod 3000 'cd e2e && jest'" -``` -El `package.json` acepta pares de parámetos (lanza un servidor y una URl para comprobar que está ejecutandose). Además acepta comandos npm ( para una instancia de la webapp en producción, con `npm run prod`) y el último parámetro lanzará jest para que ejecute los tests E2E. - -### Tests de carga (Gatling) -Esta parte se llevará a cabo utilizando [Gatling](https://gatling.io/). Gatling simulará la carga de datos en nuestro sistema haciendo peticiones a la webapp. - -Para utilizara Gatling para hacer los tests de carga en nuestra aplicación necesitamos [descargarlo](https://gatling.io/open-source/start-testing/). Basicamenre el programa tiene dos partes. Una [grabadora](https://gatling.io/docs/current/http/recorder) que capturará las acciones que queramos testear y un progrma que ejecute estas acciones y que recoja los resultados. Gatling se encargará de capturar todos los tiempos de respuesta de nuestras peticiones de nuestras peticiones y las presentará graficamente en unos gráficos para un análisis posterior. - -Una vez descargado Gatling necesitamos inicializar la [grabadora](https://gatling.io/docs/current/http/recorder). No es más que un proxy que intercepta todas las acciones que se llevan a cabo en nuestro navegador. Eso significa que tenemos que configurar nuestro navegador para que utilize ese proxy siguiendo los siguientes pasos: - -1. Configurar la grabadora en **HTTP proxy mode**. -2. Configurar el **modo HTTPs** para "Certificate Authority". -3. Generar un **certificado CA** y una key. Para esto hay que hacer click en el botón "Generate CA" . Tendrás que escoger el directorio para generar los certificados. Se crearán 2 achivos pem. -4. Configurar Firefox para utilizar estos **certificados CA** (Preferences>Certificates, import the generated certificate). -5. Configurar FireFox para utilizar un **proxy** (Preferences>Network configuration). El proxy estará en localhost:8000. -6. Configurar Firefox para que utilice el proxy incluso si la llamada se produce desde una dirección local. Para esto necesitamos configurar la propiedad `network.proxy.allow_hijacking_localhost` a `true` en `about:config`. - -Una vez tengamos la grabadora configurada y la apliación corriendo (en Heroku por ejemplo), podemos comenzar nuestro primer test. Necesitamos especificar un paquete y un nombre de clase para organizar los tests. El paquete será un directorio y el nombre de clase el nombre del test. En mi caso he utilizado `GetUserList`sin nombre de paquete. Despues de presionar "inicio" la grabadora comenzará a capturar las acciones que hagamos en el navegador. En este momento debes llevar a cabo todas las acciones que quieras grabar. En este caso he navegado hasta la página principal de la webapp y he añadido un usuario. Una vez dejemos de grabar, la simulación se almacenará en el directorio `user-files/simulations`. Escrito en lenguaje [Scala](https://www.scala-lang.org/). Si quieres ver el resultado de un test hecho con gatling puedes verlo en `webapp/loadtestexample`. Ten en cuenta que en esta simulación hay una petición post a la restapi. Los datos que se envián en una petitición post, son almacenados por gattling en el directorio `user-files/resources`. - - -Podemos modificar nuestro test de carga ,por ejemplo, inyectando 20 usuarios al mismo tiempo: -``` -setUp(scn.inject(constantUsersPerSec(3).during(15))).protocols(httpProtocol) -``` -cambiarlo en el achivo scala. Revisa [esta página](https://gatling.io/docs/gatling/reference/current/core/injection/) para tener más información sobre como inyectar carga en nuestros tests de carga. - -Para correr los tests necesitmos ejecutar: -``` -gatling.sh -s GetUserList -``` -Se mostrará una vista general de los resultados en la consola, además podremos ver un informe completo en formato wen en el directorio de los resultados. - -Es importante saber que podedmos dockerizar estos tests de carga utilizando esta [imagen](https://hub.docker.com/r/denvazh/gatling). Tan solo es cuestión de decirle al archivo docker donde se encuentra tu configuración de gatlin y los archivos scala. La imagen hará el resto.