Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Parte 1: Web/Android

Nota: este artículo es una traducción al ruso del artículo original. “Las herramientas DevOps no son sólo para DevOps. "Construir una infraestructura de automatización de pruebas desde cero". Sin embargo, todas las ilustraciones, enlaces, citas y términos se conservan en el idioma original para evitar distorsiones del significado cuando se traducen al ruso. ¡Te deseo felices estudios!

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Actualmente, la especialidad DevOps es una de las más demandadas en la industria TI. Si abre sitios populares de búsqueda de empleo y filtra por salario, verá que los trabajos relacionados con DevOps están en la parte superior de la lista. Sin embargo, es importante entender que esto se refiere principalmente a un puesto 'Senior', lo que implica que el candidato tiene un alto nivel de habilidades, conocimiento de tecnología y herramientas. Esto también conlleva un alto grado de responsabilidad asociado con el funcionamiento ininterrumpido de la producción. Sin embargo, empezamos a olvidar qué es DevOps. Inicialmente, no se trataba de ninguna persona o departamento específico. Si buscamos definiciones de este término, encontraremos muchos sustantivos hermosos y correctos, como metodología, prácticas, filosofía cultural, grupo de conceptos, etc.

Mi especialización es un ingeniero de automatización de pruebas (ingeniero de automatización de control de calidad), pero creo que no debería estar asociado únicamente con la escritura de pruebas automáticas o el desarrollo de una arquitectura de marco de pruebas. En 2020, el conocimiento de la infraestructura de automatización también es fundamental. Esto le permite organizar el proceso de automatización usted mismo, desde ejecutar pruebas hasta proporcionar resultados a todas las partes interesadas de acuerdo con sus objetivos. Como resultado, las habilidades de DevOps son imprescindibles para realizar el trabajo. Y todo esto está bien, pero lamentablemente hay un problema (spoiler: este artículo intenta simplificar este problema). La cuestión es que DevOps es difícil. Y esto es obvio, porque las empresas no pagarán mucho por algo que sea fácil de hacer... En el mundo DevOps, hay una gran cantidad de herramientas, términos y prácticas que es necesario dominar. Esto es especialmente difícil al comienzo de una carrera y depende de la experiencia técnica acumulada.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.
Fuente: http://maximelanciauxbi.blogspot.com/2017/04/devops-tools.html

Aquí probablemente terminaremos con la parte introductoria y nos centraremos en el propósito de este artículo. 

De qué se trata este artículo

En este artículo, voy a compartir mi experiencia en la construcción de una infraestructura de automatización de pruebas. Hay muchas fuentes de información en Internet sobre diversas herramientas y cómo utilizarlas, pero me gustaría examinarlas únicamente en el contexto de la automatización. Creo que muchos ingenieros de automatización están familiarizados con la situación en la que nadie, excepto usted, ejecuta las pruebas desarrolladas o se preocupa por mantenerlas. Como resultado, las pruebas quedan obsoletas y hay que dedicar tiempo a actualizarlas. Nuevamente, al comienzo de una carrera, esto puede ser una tarea bastante difícil: decidir sabiamente qué herramientas deberían ayudar a eliminar un problema determinado, cómo seleccionarlas, configurarlas y mantenerlas. Algunos evaluadores recurren a DevOps (humanos) en busca de ayuda y, seamos honestos, este enfoque funciona. En muchos casos, esta puede ser la única opción, ya que no tenemos visibilidad de todas las dependencias. Pero como sabemos, los DevOps son personas muy ocupadas, porque tienen que pensar en toda la infraestructura, implementación, monitoreo, microservicios y otras tareas similares de toda la empresa dependiendo de la organización/equipo. Como suele ocurrir, la automatización no es una prioridad. En tal caso, debemos intentar poner todo lo posible de nuestra parte de principio a fin. Esto reducirá las dependencias, acelerará el flujo de trabajo, mejorará nuestras habilidades y nos permitirá ver el panorama más amplio de lo que está sucediendo.

El artículo presenta las herramientas más populares y populares y muestra cómo usarlas para construir una infraestructura de automatización paso a paso. Cada grupo está representado por herramientas que han sido probadas a través de la experiencia personal. Pero eso no significa que tengas que usar lo mismo. Las herramientas en sí no son importantes, aparecen y se vuelven obsoletas. Nuestra tarea de ingeniería es comprender los principios básicos: por qué necesitamos este grupo de herramientas y qué problemas de trabajo podemos resolver con su ayuda. Es por eso que al final de cada sección dejo enlaces a herramientas similares que pueden usarse en su organización.

Lo que no está en este artículo.

Repito una vez más que el artículo no trata sobre herramientas específicas, por lo que no habrá inserciones de código de la documentación ni descripciones de comandos específicos. Pero al final de cada sección dejo enlaces para un estudio detallado.

Esto se hace porque: 

  • este material es muy fácil de encontrar en diversas fuentes (documentación, libros, cursos en vídeo);
  • si empezamos a profundizar, tendremos que escribir 10, 20, 30 partes de este artículo (mientras que los planes son 2-3);
  • Simplemente no quiero hacerle perder el tiempo, ya que es posible que desee utilizar otras herramientas para lograr los mismos objetivos.

Práctica

Realmente me gustaría que este material fuera útil para todos los lectores, y no solo leído y olvidado. En cualquier estudio, la práctica es un componente muy importante. Para esto he preparado Repositorio de GitHub con instrucciones paso a paso sobre cómo hacer todo desde cero. También hay tarea esperándote para asegurarte de no copiar sin pensar las líneas de los comandos que estás ejecutando.

plan

paso
Tecnología
Herramientas

1
Ejecución local (prepare pruebas de demostración web/android y ejecútelas localmente) 
Node.js, Selenio, Appium

2
Sistemas de control de versiones 
Git

3
Contenedorización
Docker, Selenium grid, Selenoid (Web, Android)

4
CI/CD
CI de Gitlab

5
Plataformas en la nube
Google Cloud Platform

6
Orquestación
Kubernetes

7
Infraestructura como código (IaC)
Terraformar, Ansible

Estructura de cada sección

Para mantener la narrativa clara, cada sección se describe de acuerdo con el siguiente esquema:

  • breve descripción de la tecnología,
  • valor para la infraestructura de automatización,
  • ilustración del estado actual de la infraestructura,
  • enlaces para estudiar,
  • herramientas similares.

1. Ejecute pruebas localmente

Breve descripción de la tecnología.

Este es solo un paso preparatorio para ejecutar las pruebas de demostración localmente y verificar que se aprueben. En la parte práctica se utiliza Node.js, pero el lenguaje de programación y la plataforma tampoco son importantes y puedes utilizar los que se utilizan en tu empresa. 

Sin embargo, como herramientas de automatización, recomiendo usar Selenium WebDriver para plataformas web y Appium para la plataforma Android, respectivamente, ya que en los próximos pasos usaremos imágenes de Docker que están diseñadas para trabajar específicamente con estas herramientas. Además, en cuanto a los requisitos laborales, estas herramientas son las más demandadas en el mercado.

Como habrás notado, solo consideramos pruebas web y de Android. Desafortunadamente, iOS es una historia completamente diferente (gracias Apple). Planeo mostrar soluciones y prácticas relacionadas con IOS en las próximas partes.

Valor para la infraestructura de automatización

Desde una perspectiva de infraestructura, la ejecución local no aporta ningún valor. Solo verifica que las pruebas se ejecuten en la máquina local en navegadores y simuladores locales. Pero en cualquier caso, éste es un punto de partida necesario.

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares

  • cualquier lenguaje de programación que desee junto con las pruebas de Selenium/Appium;
  • cualquier prueba;
  • cualquier corredor de pruebas.

2. Sistemas de control de versiones (Git)

Breve descripción de la tecnología.

No será una gran revelación para nadie si digo que el control de versiones es una parte extremadamente importante del desarrollo, tanto en equipo como individualmente. Según diversas fuentes, es seguro decir que Git es el representante más popular. Un sistema de control de versiones proporciona muchos beneficios, como compartir código, almacenar versiones, restaurar ramas anteriores, monitorear el historial del proyecto y realizar copias de seguridad. No entraremos en detalles sobre cada punto, ya que estoy seguro de que lo conoces muy bien y lo utilizas en tu trabajo diario. Pero si de repente no es así, recomiendo hacer una pausa en la lectura de este artículo y llenar este vacío lo antes posible.

Valor para la infraestructura de automatización

Y aquí puedes hacer una pregunta razonable: “¿Por qué nos habla de Git? Todo el mundo lo sabe y lo utiliza tanto para el código de desarrollo como para el código de prueba automática”. Tendrás toda la razón, pero en este artículo estamos hablando de infraestructura y esta sección actúa como una vista previa de la sección 7: “Infraestructura como código (IaC)”. Para nosotros, esto significa que toda la infraestructura, incluidas las pruebas, se describe en forma de código, por lo que también podemos aplicarle sistemas de control de versiones y obtener beneficios similares a los del código de desarrollo y automatización.

Veremos IaC con más detalle en el Paso 7, pero incluso ahora puedes comenzar a usar Git localmente creando un repositorio local. El panorama general se ampliará cuando agreguemos un repositorio remoto a la infraestructura.

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares

3. Contenedorización (Docker)

Breve descripción de la tecnología.

Para demostrar cómo la contenedorización ha cambiado las reglas del juego, retrocedamos algunas décadas en el tiempo. En aquel entonces, la gente compraba y usaba máquinas servidor para ejecutar aplicaciones. Pero en la mayoría de los casos, los recursos iniciales necesarios no se conocían de antemano. Como resultado, las empresas gastaron dinero en la compra de servidores potentes y costosos, pero parte de esta capacidad no se utilizó por completo.

La siguiente etapa de evolución fueron las máquinas virtuales (VM), que resolvieron el problema de desperdiciar dinero en recursos no utilizados. Esta tecnología permitía ejecutar aplicaciones de forma independiente entre sí dentro de un mismo servidor, asignando un espacio completamente aislado. Pero, lamentablemente, cualquier tecnología tiene sus inconvenientes. Ejecutar una VM requiere un sistema operativo completo, que consume CPU, RAM, almacenamiento y, dependiendo del sistema operativo, se deben tener en cuenta los costos de licencia. Estos factores afectan la velocidad de carga y dificultan la portabilidad.

Y ahora llegamos a la contenedorización. Una vez más, esta tecnología soluciona el problema anterior, ya que los contenedores no utilizan un sistema operativo completo, lo que libera una gran cantidad de recursos y proporciona una solución de portabilidad rápida y flexible.

Por supuesto, la tecnología de contenedorización no es nada nuevo y se introdujo por primera vez a finales de los años 70. En aquellos días se llevaron a cabo muchas investigaciones, desarrollos e intentos. Pero fue Docker quien adaptó esta tecnología y la hizo fácilmente accesible para las masas. Hoy en día, cuando hablamos de contenedores, en la mayoría de los casos nos referimos a Docker. Cuando hablamos de contenedores Docker, nos referimos a contenedores Linux. Podemos utilizar sistemas Windows y macOS para ejecutar contenedores, pero es importante entender que en este caso aparece una capa adicional. Por ejemplo, Docker en Mac ejecuta contenedores de forma silenciosa dentro de una máquina virtual Linux liviana. Volveremos a este tema cuando analicemos la ejecución de emuladores de Android dentro de contenedores, por lo que aquí hay un matiz muy importante que debe analizarse con más detalle.

Valor para la infraestructura de automatización

Descubrimos que la contenedorización y Docker son geniales. Miremos esto en el contexto de la automatización, porque cada herramienta o tecnología necesita resolver un problema. Resumamos los problemas obvios de la automatización de pruebas en el contexto de las pruebas de UI:

  • una gran cantidad de dependencias al instalar Selenium y especialmente Appium;
  • problemas de compatibilidad entre versiones de navegadores, simuladores y controladores;
  • falta de espacio aislado para navegadores/simuladores, lo cual es especialmente crítico para la ejecución en paralelo;
  • difícil de administrar y mantener si necesita ejecutar 10, 50, 100 o incluso 1000 navegadores al mismo tiempo.

Pero dado que Selenium es la herramienta de automatización más popular y Docker es la herramienta de contenedorización más popular, no debería sorprender que alguien haya intentado combinarlas para crear una herramienta poderosa para resolver los problemas mencionados anteriormente. Consideremos tales soluciones con más detalle. 

Cuadrícula de selenio en Docker

Esta herramienta es la más popular en el mundo de Selenium para ejecutar múltiples navegadores en múltiples máquinas y administrarlos desde un centro central. Para comenzar, debe registrar al menos 2 partes: Hub y Nodo(s). Hub es un nodo central que recibe todas las solicitudes de las pruebas y las distribuye a los nodos apropiados. Para cada Nodo podemos configurar una configuración específica, por ejemplo, especificando el navegador deseado y su versión. Sin embargo, aún debemos encargarnos nosotros mismos de los controladores de navegador compatibles e instalarlos en los Nodos deseados. Por esta razón, Selenium grid no se utiliza en su forma pura, excepto cuando necesitamos trabajar con navegadores que no se pueden instalar en el sistema operativo Linux. Para todos los demás casos, una solución significativamente flexible y correcta sería utilizar imágenes de Docker para ejecutar Selenium grid Hub y Nodes. Este enfoque simplifica enormemente la gestión de nodos, ya que podemos seleccionar la imagen que necesitamos con versiones compatibles de navegadores y controladores ya instalados.

A pesar de las críticas negativas sobre la estabilidad, especialmente cuando se ejecuta una gran cantidad de nodos en paralelo, Selenium grid sigue siendo la herramienta más popular para ejecutar pruebas de Selenium en paralelo. Es importante tener en cuenta que constantemente aparecen varias mejoras y modificaciones de esta herramienta en código abierto, que combaten varios cuellos de botella.

Selenoide para Web

Esta herramienta es un gran avance en el mundo de Selenium, ya que funciona desde el primer momento y ha hecho la vida de muchos ingenieros de automatización mucho más fácil. En primer lugar, esta no es otra modificación de la red Selenium. En cambio, los desarrolladores crearon una versión completamente nueva de Selenium Hub en Golang, que, combinada con imágenes ligeras de Docker para varios navegadores, impulsó el desarrollo de la automatización de pruebas. Además, en el caso de Selenium Grid, debemos determinar de antemano todos los navegadores necesarios y sus versiones, lo que no supone un problema cuando se trabaja con un solo navegador. Pero cuando se trata de múltiples navegadores compatibles, Selenoid es la solución número uno gracias a su función de "navegador bajo demanda". Todo lo que se requiere de nosotros es descargar las imágenes necesarias con los navegadores con anticipación y actualizar el archivo de configuración con el que interactúa Selenoid. Después de que Selenoid reciba una solicitud de las pruebas, iniciará automáticamente el contenedor deseado con el navegador deseado. Cuando se complete la prueba, Selenoid retirará el contenedor, liberando así recursos para futuras solicitudes. Este enfoque elimina por completo el conocido problema de la "degradación de nodos" que encontramos a menudo en la red Selenium.

Pero, por desgracia, Selenoid todavía no es una solución milagrosa. Tenemos la función "navegador a pedido", pero la función "recursos a pedido" aún no está disponible. Para usar Selenoid, debemos implementarlo en hardware físico o en una VM, lo que significa que debemos saber de antemano cuántos recursos deben asignarse. Supongo que esto no es un problema para proyectos pequeños que ejecutan 10, 20 o incluso 30 navegadores en paralelo. ¿Pero qué pasa si necesitamos 100, 500, 1000 y más? No tiene sentido mantener y pagar tantos recursos todo el tiempo. En las secciones 5 y 6 de este artículo, analizaremos soluciones que le permitirán escalar, reduciendo así significativamente los costos de la empresa.

Selenoide para Android

Tras el éxito de Selenoid como herramienta de automatización web, la gente quería algo similar para Android. Y sucedió: Selenoid fue lanzado con soporte para Android. Desde el punto de vista del usuario de alto nivel, el principio de funcionamiento es similar al de la automatización web. La única diferencia es que en lugar de contenedores de navegador, Selenoid ejecuta contenedores de emulador de Android. En mi opinión, esta es actualmente la herramienta gratuita más poderosa para ejecutar pruebas de Android en paralelo.

Realmente no me gustaría hablar sobre los aspectos negativos de esta herramienta, ya que realmente me gusta. Pero aún así, existen las mismas desventajas que se aplican a la automatización web y están asociadas con el escalamiento. Además de esto, hay que hablar de una limitación más que puede resultar sorprendente si configuramos la herramienta por primera vez. Para ejecutar imágenes de Android, necesitamos una máquina física o VM con soporte de virtualización anidada. En la guía práctica, demuestro cómo habilitar esto en una máquina virtual Linux. Sin embargo, si es un usuario de macOS y desea implementar Selenoid localmente, no será posible ejecutar pruebas de Android. Pero siempre puede ejecutar una máquina virtual Linux localmente con la 'virtualización anidada' configurada e implementar Selenoid en su interior.

Ilustración del estado actual de la infraestructura.

En el contexto de este artículo, agregaremos 2 herramientas para ilustrar la infraestructura. Estos son Selenium grid para pruebas web y Selenoid para pruebas de Android. En el tutorial de GitHub, también te mostraré cómo usar Selenoid para ejecutar pruebas web. 

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares

  • Existen otras herramientas de contenedorización, pero Docker es la más popular. Si desea probar algo más, tenga en cuenta que las herramientas que hemos cubierto para ejecutar pruebas de Selenium en paralelo no funcionarán de inmediato.  
  • Como ya se dijo, hay muchas modificaciones de la red Selenium, por ejemplo, Zalenio.

4.CI/CD

Breve descripción de la tecnología.

La práctica de la integración continua es bastante popular en el desarrollo y está a la par de los sistemas de control de versiones. A pesar de esto, siento que hay confusión en la terminología. En este párrafo me gustaría describir 3 modificaciones de esta tecnología desde mi punto de vista. En Internet encontrarás muchos artículos con diferentes interpretaciones, y es absolutamente normal que tu opinión difiera. Lo más importante es que estés en sintonía con tus compañeros.

Entonces, hay 3 términos: CI - Integración continua, CD - Entrega continua y nuevamente CD - Despliegue continuo. (A continuación usaré estos términos en inglés.). Cada modificación agrega varios pasos adicionales a su proceso de desarrollo. Pero la palabra continuo (continuo) es lo más importante. En este contexto, nos referimos a algo que sucede de principio a fin, sin interrupción ni intervención manual. Veamos CI, CD y CD en este contexto.

  • Integración continua Este es el paso inicial de la evolución. Después de enviar el nuevo código al servidor, esperamos recibir comentarios rápidos de que nuestros cambios están bien. Normalmente, la CI incluye la ejecución de herramientas de análisis de código estático y pruebas de API unitarias/internas, lo que nos permite obtener información sobre nuestro código en unos pocos segundos/minutos.
  • Entrega Continua es un paso más avanzado en el que ejecutamos pruebas de integración/UI. Sin embargo, en esta etapa no obtenemos resultados tan rápido como con la IC. En primer lugar, este tipo de pruebas tardan más en completarse. En segundo lugar, antes del lanzamiento, debemos implementar nuestros cambios en el entorno de prueba/ensayo. Además, si hablamos de desarrollo móvil, entonces aparece un paso adicional para crear una compilación de nuestra aplicación.
  • Entregas Continuas asume que lanzamos automáticamente nuestros cambios a producción si se han pasado todas las pruebas de aceptación en las etapas anteriores. Además de esto, después de la etapa de lanzamiento, puede configurar varias etapas, como ejecutar pruebas de humo en producción y recopilar métricas de interés. La implementación continua solo es posible con una buena cobertura mediante pruebas automatizadas. Si se requiere alguna intervención manual, incluidas pruebas, esto ya no es posible. ASESORIA CONTINUA (continuo). Entonces podemos decir que nuestro pipeline cumple únicamente con la práctica de Entrega Continua.

Valor para la infraestructura de automatización

En esta sección, debo aclarar que cuando hablamos de pruebas de UI de un extremo a otro, significa que debemos implementar nuestros cambios y servicios asociados en los entornos de prueba. Integración Continua: el proceso no es aplicable para esta tarea y debemos encargarnos de implementar al menos prácticas de Entrega Continua. La implementación continua también tiene sentido en el contexto de las pruebas de UI si vamos a ejecutarlas en producción.

Y antes de ver la ilustración del cambio de arquitectura, quiero decir algunas palabras sobre GitLab CI. A diferencia de otras herramientas de CI/CD, GitLab proporciona un repositorio remoto y muchas otras funciones adicionales. Por tanto, GitLab es más que CI. Incluye gestión de código fuente, gestión ágil, canales de CI/CD, herramientas de registro y recopilación de métricas listas para usar. La arquitectura de GitLab consta de Gitlab CI/CD y GitLab Runner. Aquí hay una breve descripción del sitio web oficial:

Gitlab CI/CD es una aplicación web con una API que almacena su estado en una base de datos, gestiona proyectos/compilaciones y proporciona una interfaz de usuario. GitLab Runner es una aplicación que procesa compilaciones. Se puede implementar por separado y funciona con GitLab CI/CD a través de una API. Para ejecutar pruebas, necesita tanto la instancia de Gitlab como Runner.

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares

5. Plataformas en la nube

Breve descripción de la tecnología.

En esta sección hablaremos de una tendencia popular llamada "nubes públicas". A pesar de los enormes beneficios que brindan las tecnologías de virtualización y contenedorización descritas anteriormente, todavía necesitamos recursos informáticos. Las empresas compran servidores caros o alquilan centros de datos, pero en este caso es necesario hacer cálculos (a veces poco realistas) de cuántos recursos necesitaremos, si los usaremos 24 horas al día, 7 días a la semana y con qué fines. Por ejemplo, la producción requiere un servidor que funcione las XNUMX horas del día, los XNUMX días de la semana, pero ¿necesitamos recursos similares para realizar pruebas fuera del horario laboral? También depende del tipo de prueba que se realice. Un ejemplo serían las pruebas de carga/estrés que planeamos ejecutar fuera del horario laboral para obtener resultados al día siguiente. Pero definitivamente no se requiere disponibilidad del servidor XNUMX horas al día, XNUMX días a la semana para pruebas automatizadas de un extremo a otro y especialmente para entornos de pruebas manuales. Para tales situaciones, sería bueno obtener tantos recursos como sea necesario a pedido, usarlos y dejar de pagar cuando ya no sean necesarios. Además, sería genial recibirlos instantáneamente haciendo unos pocos clics del mouse o ejecutando un par de scripts. Para esto se utilizan las nubes públicas. Veamos la definición:

“La nube pública se define como servicios informáticos ofrecidos por terceros proveedores a través de la Internet pública, poniéndolos a disposición de cualquiera que quiera usarlos o comprarlos. Pueden ser gratuitos o venderse bajo demanda, lo que permite a los clientes pagar sólo por el uso de los ciclos de CPU, el almacenamiento o el ancho de banda que consumen".

Existe la opinión de que las nubes públicas son caras. Pero su idea clave es reducir los costes de la empresa. Como se mencionó anteriormente, las nubes públicas le permiten obtener recursos a pedido y pagar solo por el tiempo que los usa. Además, a veces nos olvidamos de que los empleados reciben salarios y los especialistas también son un recurso caro. Hay que tener en cuenta que las nubes públicas facilitan mucho el soporte de la infraestructura, lo que permite a los ingenieros centrarse en tareas más importantes. 

Valor para la infraestructura de automatización

¿Qué recursos específicos necesitamos para las pruebas de UI de un extremo a otro? Básicamente se trata de máquinas virtuales o clústeres (hablaremos de Kubernetes en la siguiente sección) para ejecutar navegadores y emuladores. Cuantos más navegadores y emuladores queramos ejecutar simultáneamente, más CPU y memoria se necesitarán y más dinero tendremos que pagar por ello. Por lo tanto, las nubes públicas en el contexto de la automatización de pruebas nos permiten ejecutar una gran cantidad (100, 200, 1000...) de navegadores/emuladores bajo demanda, obtener resultados de pruebas lo más rápido posible y dejar de pagar por recursos tan increíblemente intensivos. fuerza. 

Los proveedores de nube más populares son Amazon Web Services (AWS), Microsoft Azure y Google Cloud Platform (GCP). La guía práctica proporciona ejemplos de cómo usar GCP, pero en general no importa lo que uses para las tareas de automatización. Todos proporcionan aproximadamente la misma funcionalidad. Normalmente, para seleccionar un proveedor, la gestión se centra en toda la infraestructura y los requisitos comerciales de la empresa, lo cual está fuera del alcance de este artículo. Para los ingenieros de automatización, será más interesante comparar el uso de proveedores de nube con el uso de plataformas en la nube específicamente con fines de prueba, como Sauce Labs, BrowserStack, BitBar, etc. ¡Así que hagámoslo también! En mi opinión, Sauce Labs es la granja de pruebas en la nube más famosa, por eso la usé como comparación. 

GCP vs Sauce Labs para fines de automatización:

Imaginemos que necesitamos ejecutar 8 pruebas web y 8 pruebas de Android simultáneamente. Para ello usaremos GCP y ejecutaremos 2 máquinas virtuales con Selenoid. En el primero levantaremos 8 contenedores con navegadores. En el segundo hay 8 contenedores con emuladores. Echemos un vistazo a los precios:  

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.
Para ejecutar un contenedor con Chrome, necesitamos n1-estándar-1 auto. En el caso de Android será n1-estándar-4 para un emulador. De hecho, una forma más flexible y económica es establecer valores de usuario específicos para CPU/Memoria, pero por el momento esto no es importante en comparación con Sauce Labs.

Y aquí están las tarifas por usar Sauce Labs:

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.
Creo que ya habrás notado la diferencia, pero aun así te proporcionaré una tabla con los cálculos para nuestra tarea:

Recursos necesarios
Montly
Horario laboral(8 am - 8 pm)
Horario laboral+ Prevenible

GCP para Web
n1-estándar-1 x 8 = n1-estándar-8
$194.18
23 días * 12h * 0.38 = $104.88 
23 días * 12h * 0.08 = $22.08

Laboratorios de salsa para web
Pruebas paralelas de Virtual Cloud8
$1.559
-
-

GCP para Android
n1-estándar-4 x 8: n1-estándar-16
$776.72
23 días * 12h * 1.52 = $419.52 
23 días * 12h * 0.32 = $88.32

Laboratorios de salsa para Android
Pruebas paralelas de Real Device Cloud 8
$1.999
-
-

Como puede ver, la diferencia de costo es enorme, especialmente si ejecuta pruebas solo durante un período de trabajo de doce horas. Pero puedes reducir los costos aún más si utilizas máquinas preferentes. ¿Qué es?

Una VM interrumpible es una instancia que puede crear y ejecutar a un precio mucho menor que las instancias normales. Sin embargo, Compute Engine podría finalizar (adelantar) estas instancias si requiere acceso a esos recursos para otras tareas. Las instancias preferentes son un exceso de capacidad de Compute Engine, por lo que su disponibilidad varía según el uso.

Si sus aplicaciones son tolerantes a fallas y pueden soportar posibles apropiaciones de instancias, las instancias apropiables pueden reducir significativamente sus costos de Compute Engine. Por ejemplo, los trabajos de procesamiento por lotes se pueden ejecutar en instancias interrumpibles. Si algunas de esas instancias terminan durante el procesamiento, el trabajo se ralentiza pero no se detiene por completo. Las instancias preferentes completan sus tareas de procesamiento por lotes sin imponer una carga de trabajo adicional a sus instancias existentes y sin que usted tenga que pagar el precio completo por instancias normales adicionales.

¡Y todavía no ha terminado! En realidad, estoy seguro de que nadie realiza pruebas durante 12 horas sin descanso. Y si es así, puede iniciar y detener automáticamente las máquinas virtuales cuando no sean necesarias. El tiempo de uso real puede reducirse a 6 horas por día. Entonces el pago en el contexto de nuestra tarea se reducirá a $11 por mes para 8 navegadores. ¿No es esto maravilloso? Pero con las máquinas interrumpibles debemos tener cuidado y estar preparados para las interrupciones y la inestabilidad, aunque estas situaciones pueden preverse y manejarse mediante software. ¡Vale la pena!

Pero de ninguna manera estoy diciendo "nunca utilice granjas de prueba en la nube". Tienen una serie de ventajas. En primer lugar, no se trata solo de una máquina virtual, sino de una solución de automatización de pruebas completa con un conjunto de funciones listas para usar: acceso remoto, registros, capturas de pantalla, grabación de video, varios navegadores y dispositivos móviles físicos. En muchas situaciones, esta puede ser una alternativa chic esencial. Las plataformas de prueba son especialmente útiles para la automatización de IOS, cuando las nubes públicas sólo pueden ofrecer sistemas Linux/Windows. Pero de iOS hablaremos en los siguientes artículos. Recomiendo siempre observar la situación y partir de las tareas: en algunos casos es más barato y más eficiente usar nubes públicas, y en otros, las plataformas de prueba definitivamente valen el dinero gastado.

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares:

6. Orquestación

Breve descripción de la tecnología.

Tengo buenas noticias: ¡ya casi llegamos al final del artículo! Por el momento, nuestra infraestructura de automatización consta de pruebas web y de Android, que ejecutamos a través de GitLab CI en paralelo, utilizando herramientas habilitadas para Docker: Selenium grid y Selenoid. Además, utilizamos máquinas virtuales creadas mediante GCP para alojar contenedores con navegadores y emuladores. Para reducir costos, iniciamos estas máquinas virtuales solo cuando se solicita y las detenemos cuando no se están realizando pruebas. ¿Hay algo más que pueda mejorar nuestra infraestructura? ¡La respuesta es sí! ¡Conozca Kubernetes (K8)!

Primero, veamos cómo se relacionan entre sí las palabras orquestación, clúster y Kubernetes. En un nivel alto, la orquestación es el sistema que implementa y administra aplicaciones. Para la automatización de pruebas, estas aplicaciones en contenedores son Selenium grid y Selenoid. Docker y K8 se complementan. El primero se utiliza para la implementación de aplicaciones, el segundo para la orquestación. A su vez, K8s es un grupo. La tarea del clúster es utilizar máquinas virtuales como nodos, lo que le permite instalar diversas funciones, programas y servicios dentro de un servidor (clúster). Si alguno de los Nodos falla, otros Nodos se recuperarán, lo que garantiza el funcionamiento ininterrumpido de nuestra aplicación. Además de esto, K8s tiene una importante funcionalidad relacionada con el escalado, gracias a la cual obtenemos automáticamente la cantidad óptima de recursos en función de la carga y límites establecidos.

En verdad, implementar Kubernetes manualmente desde cero no es una tarea trivial en absoluto. Te dejaré un enlace a la famosa guía práctica "Kubernetes The Hard Way" y si estás interesado, puedes practicarla. Pero, afortunadamente, existen métodos y herramientas alternativos. La forma más sencilla es utilizar Google Kubernetes Engine (GKE) en GCP, lo que le permitirá obtener un clúster listo para usar con unos pocos clics. Recomiendo usar este enfoque para comenzar a aprender, ya que le permitirá concentrarse en aprender a usar los K8 para sus tareas en lugar de aprender cómo se deben integrar los componentes internos. 

Valor para la infraestructura de automatización

Echemos un vistazo a algunas características importantes que ofrece el K8:

  • implementación de aplicaciones: uso de un clúster de múltiples nodos en lugar de máquinas virtuales;
  • escalado dinámico: reduce el costo de los recursos que se utilizan solo bajo demanda;
  • autocuración: recuperación automática de vainas (como resultado de lo cual también se restauran los contenedores);
  • Implementación de actualizaciones y reversiones de cambios sin tiempo de inactividad: la actualización de herramientas, navegadores y emuladores no interrumpe el trabajo de los usuarios actuales.

Pero el K8 todavía no es una solución milagrosa. Para comprender todas las ventajas y limitaciones en el contexto de las herramientas que estamos considerando (Selenium grid, Selenoid), discutiremos brevemente la estructura de los K8. El clúster contiene dos tipos de nodos: nodos maestros y nodos trabajadores. Los Master Nodes son responsables de las decisiones de gestión, implementación y programación. Los nodos trabajadores son donde se lanzan las aplicaciones. Los nodos también contienen un entorno de ejecución de contenedor. En nuestro caso, se trata de Docker, que es responsable de las operaciones relacionadas con los contenedores. Pero también existen soluciones alternativas, por ejemplo contenedor. Es importante comprender que el escalamiento o la autorreparación no se aplica directamente a los contenedores. Esto se implementa agregando/disminuyendo la cantidad de pods, que a su vez contienen contenedores (generalmente un contenedor por pod, pero dependiendo de la tarea puede haber más). La jerarquía de alto nivel consta de nodos trabajadores, dentro de los cuales hay pods, dentro de los cuales se levantan los contenedores.

La función de escalado es clave y se puede aplicar tanto a los nodos dentro de un grupo de nodos del clúster como a los pods dentro de un nodo. Hay dos tipos de escalamiento que se aplican tanto a los nodos como a los pods. El primer tipo es horizontal: el escalado se produce aumentando el número de nodos/pods. Este tipo es más preferible. El segundo tipo es, respectivamente, vertical. El escalado se lleva a cabo aumentando el tamaño de los nodos/pods, y no su número.

Ahora veamos nuestras herramientas en el contexto de los términos anteriores.

Rejilla de selenio

Como se mencionó anteriormente, Selenium grid es una herramienta muy popular y no sorprende que se haya incluido en contenedores. Por lo tanto, no sorprende que la red Selenium pueda implementarse en los K8. Puede encontrar un ejemplo de cómo hacer esto en el repositorio oficial de K8s. Como es habitual, adjunto enlaces al final de la sección. Además, la guía práctica muestra cómo hacer esto en Terraform. También hay instrucciones sobre cómo escalar la cantidad de pods que contienen contenedores de navegador. Pero la función de escalado automático en el contexto del K8 todavía no es una tarea del todo obvia. Cuando comencé a estudiar, no encontré ninguna guía ni recomendación práctica. Después de varios estudios y experimentos con el apoyo del equipo de DevOps, elegimos el enfoque de levantar contenedores con los navegadores necesarios dentro de un pod, que se encuentra dentro de un nodo trabajador. Este método nos permite aplicar la estrategia de escalado horizontal de nodos aumentando su número. Espero que esto cambie en el futuro y veamos cada vez más descripciones de mejores enfoques y soluciones listas para usar, especialmente después del lanzamiento de Selenium grid 4 con una arquitectura interna modificada.

selenoide:

El despliegue de selenoides en los K8 es actualmente la mayor decepción. No son compatibles. En teoría, podemos levantar un contenedor Selenoid dentro de un pod, pero cuando Selenoid comience a lanzar contenedores con navegadores, seguirán estando dentro del mismo pod. Esto hace que el escalamiento sea imposible y, como resultado, el trabajo de Selenoid dentro de un clúster no diferirá del trabajo dentro de una máquina virtual. Fin de la historia.

luna:

Conociendo este cuello de botella al trabajar con Selenoid, los desarrolladores lanzaron una herramienta más poderosa llamada Moon. Esta herramienta se diseñó originalmente para funcionar con Kubernetes y, como resultado, se puede y se debe utilizar la función de escalado automático. Además, diría que en este momento es единственный una herramienta en el mundo de Selenium, que tiene soporte nativo para clústeres K8 listo para usar (ya no está disponible, ver la siguiente herramienta ). Las características clave de Moon que brindan este soporte son: 

Completamente apátrida. Selenoid almacena en la memoria información sobre las sesiones del navegador que se están ejecutando actualmente. Si por alguna razón su proceso falla, entonces se perderán todas las sesiones en ejecución. Por el contrario, Moon no tiene estado interno y puede replicarse en centros de datos. Las sesiones del navegador permanecen activas incluso si una o más réplicas fallan.

Entonces, Moon es una gran solución, pero hay un problema: no es gratis. El precio depende del número de sesiones. Sólo puedes ejecutar de 0 a 4 sesiones de forma gratuita, lo cual no es particularmente útil. Pero, a partir de la quinta sesión, tendrás que pagar 5 dólares por cada una. La situación puede variar de una empresa a otra, pero en nuestro caso utilizar Moon no tiene sentido. Como describí anteriormente, podemos ejecutar máquinas virtuales con Selenium Grid a pedido o aumentar la cantidad de nodos en el clúster. Para aproximadamente una canalización, iniciamos 500 navegadores y detenemos todos los recursos una vez completadas las pruebas. Si usáramos Moon, tendríamos que pagar 500 x 5 adicionales = $2500 por mes, sin importar la frecuencia con la que realicemos las pruebas. Nuevamente, no estoy diciendo que no uses Moon. Para sus tareas, esta puede ser una solución indispensable, por ejemplo, si tiene muchos proyectos/equipos en su organización y necesita un gran clúster común para todos. Como siempre, dejo un enlace al final y recomiendo hacer todos los cálculos necesarios en el contexto de tu tarea.

Callisto: (¡Atención! Esto no está en el artículo original y está contenido únicamente en la traducción al ruso.)

Como dije, Selenium es una herramienta muy popular y el campo de TI se está desarrollando muy rápidamente. Mientras trabajaba en la traducción, apareció en la web una nueva herramienta prometedora llamada Callisto (hola Cypress y otros asesinos de Selenium). Funciona de forma nativa con K8 y le permite ejecutar contenedores Selenoid en pods, distribuidos entre nodos. Todo funciona desde el primer momento, incluido el ajuste de escala automático. Fantástico, pero hay que probarlo. Ya logré implementar esta herramienta y ejecutar varios experimentos. Pero es demasiado pronto para sacar conclusiones; después de recibir resultados a larga distancia, tal vez haga una revisión en futuros artículos. Por ahora solo dejo enlaces para investigaciones independientes.  

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar

Herramientas similares

7. Infraestructura como Código (IaC)

Breve descripción de la tecnología.

Y ahora llegamos al último apartado. Normalmente, esta tecnología y las tareas relacionadas no son responsabilidad de los ingenieros de automatización. Y hay razones para ello. En primer lugar, en muchas organizaciones, los problemas de infraestructura están bajo el control del departamento de DevOps y a los equipos de desarrollo realmente no les importa qué hace que el proceso funcione y cómo debe soportarse todo lo relacionado con él. En segundo lugar, seamos honestos, la práctica de la infraestructura como código (IaC) todavía no se adopta en muchas empresas. Pero definitivamente se ha convertido en una tendencia popular y es importante intentar involucrarse en los procesos, enfoques y herramientas asociados a ella. O al menos mantente actualizado.

Comencemos con la motivación para utilizar este enfoque. Ya hemos comentado que para ejecutar pruebas en GitlabCI, necesitaremos como mínimo los recursos para ejecutar Gitlab Runner. Y para ejecutar contenedores con navegadores/emuladores, necesitamos reservar una VM o un clúster. Además de los recursos de prueba, necesitamos una cantidad significativa de capacidad para soportar entornos de desarrollo, puesta en escena y producción, que también incluyen bases de datos, programaciones automáticas, configuraciones de red, balanceadores de carga, derechos de usuario, etc. La cuestión clave es el esfuerzo necesario para respaldarlo todo. Hay varias formas en que podemos realizar cambios e implementar actualizaciones. Por ejemplo, en el contexto de GCP, podemos usar la consola UI en el navegador y realizar todas las acciones haciendo clic en los botones. Una alternativa sería utilizar llamadas API para interactuar con entidades de la nube o utilizar la utilidad de línea de comandos gcloud para realizar las manipulaciones deseadas. Pero con una cantidad realmente grande de entidades y elementos de infraestructura diferentes, resulta difícil o incluso imposible realizar todas las operaciones manualmente. Además, todas estas acciones manuales son incontrolables. No podemos enviarlos para su revisión antes de su ejecución, utilizar un sistema de control de versiones y revertir rápidamente los cambios que provocaron el incidente. Para resolver tales problemas, los ingenieros crearon y crean scripts bash/shell automáticos, que no son mucho mejores que los métodos anteriores, ya que no son tan fáciles de leer, comprender, mantener y modificar rápidamente en un estilo procedimental.

En este artículo y guía práctica, utilizo dos herramientas relacionadas con la práctica de IaC. Estos son Terraform y Ansible. Algunas personas creen que no tiene sentido utilizarlos al mismo tiempo, ya que su funcionalidad es similar y son intercambiables. Pero el hecho es que inicialmente se les asignan tareas completamente diferentes. Y el hecho de que estas herramientas deberían complementarse entre sí lo confirmó una presentación conjunta de los desarrolladores que representan a HashiCorp y RedHat. La diferencia conceptual es que Terraform es una herramienta de aprovisionamiento para gestionar los propios servidores. Mientras que Ansible es una herramienta de gestión de configuración cuya tarea es instalar, configurar y gestionar software en estos servidores.

Otra característica distintiva clave de estas herramientas es el estilo de codificación. A diferencia de bash y Ansible, Terraform utiliza un estilo declarativo basado en una descripción del estado final deseado que se alcanzará como resultado de la ejecución. Por ejemplo, si vamos a crear 10 VM y aplicar los cambios a través de Terraform, obtendremos 10 VM. Si ejecutamos el script nuevamente, no pasará nada ya que ya tenemos 10 VM y Terraform lo sabe porque almacena el estado actual de la infraestructura en un archivo de estado. Pero Ansible utiliza un enfoque procedimental y, si le pide que cree 10 VM, en el primer lanzamiento obtendremos 10 VM, similar a Terraform. Pero tras reiniciar ya tendremos 20 VM. Ésta es la diferencia importante. En el estilo procesal, no almacenamos el estado actual y simplemente describimos una secuencia de pasos que deben realizarse. Por supuesto, podemos manejar varias situaciones, agregar varias comprobaciones de la existencia de recursos y el estado actual, pero no tiene sentido perder el tiempo y esforzarnos en controlar esta lógica. Además, esto aumenta el riesgo de cometer errores. 

Resumiendo todo lo anterior, podemos concluir que Terraform y la notación declarativa son una herramienta más adecuada para aprovisionar servidores. Pero es mejor delegar el trabajo de gestión de la configuración en Ansible. Dejando eso de lado, veamos los casos de uso en el contexto de la automatización.

Valor para la infraestructura de automatización

Lo único importante que hay que entender aquí es que la infraestructura de automatización de pruebas debe considerarse parte de toda la infraestructura de la empresa. Esto significa que todas las prácticas de IaC deben aplicarse globalmente a los recursos de toda la organización. Quién es responsable de esto depende de sus procesos. El equipo de DevOps tiene más experiencia en estos temas y ve el panorama completo de lo que está sucediendo. Sin embargo, los ingenieros de control de calidad están más involucrados en el proceso de automatización de edificios y en la estructura de la tubería, lo que les permite ver mejor todos los cambios requeridos y las oportunidades de mejora. La mejor opción es trabajar juntos, intercambiar conocimientos e ideas para lograr el resultado esperado. 

A continuación se muestran algunos ejemplos del uso de Terraform y Ansible en el contexto de la automatización de pruebas y las herramientas que analizamos antes:

1. Describir las características y parámetros necesarios de las máquinas virtuales y los clústeres que utilizan Terraform.

2. Usando Ansible, instale las herramientas necesarias para las pruebas: Docker, Selenoid, Selenium Grid y descargue las versiones requeridas de navegadores/emuladores.

3. Usando Terraform, describa las características de la VM en la que se lanzará GitLab Runner.

4. Instale GitLab Runner y las herramientas complementarias necesarias utilizando Ansible, establezca ajustes y configuraciones.

Ilustración del estado actual de la infraestructura.

Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Enlaces para explorar:

Herramientas similares

¡Resumamos!

paso
Tecnología
Herramientas
Valor para la infraestructura de automatización

1
Ejecución local
Node.js, Selenio, Appium

  • Las herramientas más populares para web y móvil
  • Admite muchos idiomas y plataformas (incluido Node.js)

2
Sistemas de control de versiones 
Git

  • Beneficios similares con código de desarrollo

3
Contenedorización
Docker, Selenium grid, Selenoid (Web, Android)

  • Ejecución de pruebas en paralelo
  • Ambientes aislados
  • Actualizaciones de versiones simples y flexibles
  • Detener dinámicamente los recursos no utilizados
  • Fácil de configurar

4
CI/CD
CI de Gitlab

  • Prueba parte del proceso
  • Comentarios rápidos
  • Visibilidad para toda la empresa/equipo

5
Plataformas en la nube
Google Cloud Platform

  • Recursos bajo demanda (pagamos solo cuando es necesario)
  • Fácil de administrar y actualizar
  • Visibilidad y control de todos los recursos.

6
Orquestación
Kubernetes
En el contexto de contenedores con navegadores/emuladores dentro de pods:

  • Escalado/escalado automático
  • Autosanación
  • Actualizaciones y reversiones sin interrupción

7
Infraestructura como código (IaC)
Terraformar, Ansible

  • Beneficios similares con infraestructura de desarrollo.
  • Todos los beneficios del versionado de código
  • Fácil de realizar cambios y mantener
  • Completamente automatizado

Diagramas de mapas mentales: evolución de la infraestructura

paso 1: local
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

paso 2: VCS
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

paso 3: contenedorización 
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

paso 4: CI/CD 
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

Paso 5: Plataformas en la nube
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

paso 6: Orquestación
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

paso 7: IaC
Las herramientas DevOps no son sólo para DevOps. El proceso de construcción de una infraestructura de automatización de pruebas desde cero.

¿Qué será lo próximo?

Entonces, este es el final del artículo. Pero para concluir, me gustaría establecer algunos acuerdos con usted.

De tu lado
Como dije al principio, me gustaría que el artículo fuera de utilidad práctica y te ayudara a aplicar los conocimientos adquiridos en el trabajo real. agrego de nuevo enlace a la guía práctica.

Pero incluso después de eso, no te detengas, practica, estudia enlaces y libros relevantes, descubre cómo funciona en tu empresa, encuentra lugares que se pueden mejorar y participa. ¡Buena suerte!

De mi parte

Por el título se puede ver que esta fue sólo la primera parte. A pesar de que resultó ser bastante extenso, aquí todavía no se tratan temas importantes. En la segunda parte, planeo analizar la infraestructura de automatización en el contexto de IOS. Debido a las restricciones de Apple sobre la ejecución de simuladores de iOS solo en sistemas macOS, nuestra gama de soluciones se reduce. Por ejemplo, no podemos usar Docker para ejecutar el simulador ni nubes públicas para ejecutar máquinas virtuales. Pero esto no significa que no existan otras alternativas. ¡Intentaré mantenerte actualizado con soluciones avanzadas y herramientas modernas!

Además, no he mencionado temas muy importantes relacionados con el seguimiento. En la Parte 3, analizaré las herramientas de monitoreo de infraestructura más populares y qué datos y métricas considerar.

Y finalmente. En el futuro, planeo lanzar un curso en video sobre cómo crear infraestructura de prueba y herramientas populares. Actualmente, hay bastantes cursos y conferencias sobre DevOps en Internet, pero todos los materiales se presentan en el contexto del desarrollo, no de la automatización de pruebas. Sobre este tema, realmente necesito comentarios sobre si dicho curso será interesante y valioso para la comunidad de evaluadores e ingenieros de automatización. ¡Gracias de antemano!

Fuente: habr.com

Añadir un comentario