Prueba de proyectos de Node.js. Parte 2. Evaluación del rendimiento de la prueba, integración continua y análisis de calidad del código.

Prueba de proyectos de Node.js. Parte 1. Anatomía de prueba y tipos de prueba

Hoy, en la segunda parte de la traducción del material dedicado a probar proyectos de Node.js, hablaremos sobre la evaluación de la efectividad de las pruebas y el análisis de la calidad del código.

imagen

Sección 3. Evaluación de la efectividad de las pruebas.


▍19. Logre un nivel suficientemente alto de cobertura de código con pruebas para ganar confianza en su correcto funcionamiento. Por lo general, aproximadamente el 80% de cobertura da buenos resultados.


Recomendaciones


El propósito de las pruebas es asegurar que el programador pueda continuar trabajando productivamente en el proyecto, asegurándose de que lo que ya se hizo sea correcto. Obviamente, cuanto mayor sea el volumen del código probado, mayor será la confianza de que todo funciona como debería. El indicador de cobertura de código por pruebas indica cuántas líneas (ramas, comandos) fueron verificadas por las pruebas. ¿Cuál debería ser este indicador? Está claro que 10-30% es demasiado poco para dar confianza de que el proyecto funcionará sin errores. Por otro lado, el deseo de una cobertura del 100% del código con las pruebas puede resultar demasiado costoso y puede distraer al desarrollador de los fragmentos de programa más importantes, lo que le obliga a buscar en el código aquellos lugares a los que no llegan las pruebas existentes. Si da una respuesta más completa a la pregunta de cuál debería ser la cobertura del código con las pruebas, entonces podemos decir que el indicador al que debemos esforzarnos depende de la aplicación que se esté desarrollando. Por ejemplo, si está escribiendo software para la próxima generación de Airbus A380, entonces el 100% es un indicador que ni siquiera se discute. Pero si crea un sitio web en el que se mostrarán galerías de caricaturas, entonces probablemente el 50% ya sea mucho. Aunque los expertos en pruebas dicen que el nivel de cobertura del código con las pruebas que debe apuntar depende del proyecto, muchos de ellos mencionan la cifra del 80%, que probablemente sea adecuada para la mayoría de las aplicaciones. Por ejemplo, aquí estamos hablando de algo en la región del 80-90% y, según el autor de este material, el 100% de cobertura del código con pruebas lo hace sospechar, ya que puede indicar que el programador escribe pruebas solo para obtener Hermoso número en el informe.

Para utilizar los indicadores de las pruebas de cobertura de código, deberá configurar correctamente su sistema para una integración continua (CI, Integración continua). Esto permitirá, si el indicador correspondiente no alcanza un cierto umbral, detener el ensamblaje del proyecto. Aquí se explica cómo configurar Jest para recopilar información de cobertura de prueba. Además, puede configurar umbrales de cobertura no para todo el código, sino para centrarse en componentes individuales. Además de esto, considere detectar una disminución en la cobertura de la prueba. Esto sucede, por ejemplo, al agregar un nuevo código a un proyecto. El control de este indicador alentará a los desarrolladores a aumentar el volumen del código probado, o al menos a mantener este volumen en el nivel existente. En vista de lo anterior, la cobertura de código con pruebas es solo un indicador, cuantificado, que no es suficiente para evaluar completamente la confiabilidad de las pruebas. Además, como se mostrará a continuación, sus altos niveles aún no significan que el código "cubierto con pruebas" esté realmente verificado.

Consecuencias de la desviación de las recomendaciones


La confianza del programador en la alta calidad del código y los indicadores relacionados relacionados con las pruebas van de la mano. Un programador no puede evitar tener miedo a los errores si no sabe que la mayor parte del código para su proyecto está cubierto por pruebas. Estas preocupaciones pueden ralentizar su proyecto.

Ejemplo


Así es como se ve un informe de cobertura de prueba típico.


Informe de cobertura de prueba generado por Estambul

Enfoque correcto


Aquí hay un ejemplo de cómo establecer el nivel deseado de cobertura de prueba del código de componente y el nivel general de este indicador en Jest.


Establecer el nivel deseado de cobertura de código con pruebas para todo el proyecto y para un componente específico

▍20. Examine los informes sobre la cobertura del código con pruebas para identificar partes no protegidas del código y otras anomalías.


Recomendaciones


Algunos problemas tienden a pasar por una variedad de sistemas de detección de errores. Tales cosas pueden ser difíciles de detectar utilizando herramientas tradicionales. Quizás esto no se aplique a errores reales. Más bien, estamos hablando de un comportamiento inesperado de la aplicación, que puede tener consecuencias devastadoras. Por ejemplo, a menudo sucede que algunos fragmentos de código nunca se usan o rara vez se llaman. Por ejemplo, cree que los mecanismos de la clase PricingCalculator siempre se usan para establecer el precio de un producto, pero de hecho resulta que esta clase no se usa en absoluto, y hay registros de 10,000 productos en la base de datos, y la tienda en línea donde se usa el sistema tiene muchas ventas ... Los informes sobre la cobertura del código con las pruebas ayudan al desarrollador a comprender si la aplicación funciona como debería. Además, de los informes puede averiguar qué código de proyecto no se prueba. Si se enfoca en un indicador general que indica que las pruebas cubren el 80% del código, no puede averiguar si se están probando partes críticas de la aplicación. Para generar dicho informe, es suficiente configurar correctamente la herramienta que utiliza para ejecutar las pruebas. Tales informes generalmente se ven bastante bonitos, y su análisis, que no lleva mucho tiempo, le permite detectar todo tipo de sorpresas.

Consecuencias de la desviación de las recomendaciones


Si no sabe qué partes de su código permanecen sin probar, entonces no sabe dónde puede esperar problemas.

Enfoque equivocado


Mire el próximo informe y piense en lo que parece inusual en él.


Informe que indica un comportamiento inusual del sistema

El informe se basa en un escenario de uso real de la aplicación y le permite ver el comportamiento inusual del programa asociado con los usuarios que inician sesión en el sistema. Es decir, una cantidad inesperadamente grande de intentos fallidos de ingresar al sistema llama la atención en comparación con los exitosos. Después de analizar el proyecto, resultó que la razón de esto fue un error en la interfaz, debido a que la parte de la interfaz del proyecto enviaba constantemente las solicitudes correspondientes a la API del servidor para ingresar al sistema.

▍21. Mida la cobertura del código lógico con pruebas usando pruebas de mutación


Recomendaciones


Las métricas tradicionales de evaluación comparativa pueden no ser confiables. Entonces, en el informe puede haber una cifra del 100%, pero al mismo tiempo, absolutamente todas las funciones del proyecto devolverán valores incorrectos. ¿Cómo explicar esto? El hecho es que el indicador de cobertura de código por pruebas indica solo qué líneas de código se ejecutaron bajo el control del sistema de prueba, pero no depende de si algo se ha verificado realmente, es decir, si las declaraciones de prueba destinado a verificar la exactitud de los resultados del código. Esto se parece a una persona que, al regresar de un viaje de negocios al extranjero, muestra sellos en su pasaporte. Los sellos prueban que fue a algún lado, pero no dicen nada sobre si hizo lo que hizo en un viaje de negocios.

Aquí, las pruebas de mutación pueden ayudarnos, lo que nos permite descubrir cuánto código se probó realmente, y no solo el sistema de prueba. Para las pruebas mutacionales, puede usar la biblioteca Stryker JS. Aquí están los principios por los cuales funciona:

  1. Ella intencionalmente cambia el código, creando errores en él. Por ejemplo, el código newOrder.price===0 convierte en newOrder.price!=0 . Estos "errores" se llaman mutaciones.
  2. Ella hace pruebas. Si resultan ser aprobados, entonces tenemos problemas, porque las pruebas no cumplen con su tarea de detectar errores, y los "mutantes", como dicen, "sobreviven". Si las pruebas indican errores en el código, entonces todo está en orden: los "mutantes" "mueren".

Si resulta que todos los "mutantes" fueron "asesinados" (o, al menos, la mayoría de ellos no sobrevivieron), esto proporciona un mayor nivel de confianza en la alta calidad del código y las pruebas que lo prueban que las métricas tradicionales para cubrir el código con pruebas. Al mismo tiempo, el tiempo requerido para configurar y realizar pruebas mutacionales es comparable al necesario cuando se usan pruebas convencionales.

Consecuencias de la desviación de las recomendaciones


Si el indicador tradicional de cobertura de código por pruebas indica que el 85% del código está cubierto por pruebas, esto no significa que las pruebas puedan detectar errores en este código.

Enfoque equivocado


Aquí hay un ejemplo de cobertura del 100% del código con pruebas, en el que el código no se prueba por completo.

 function addNewOrder(newOrder) {   logger.log(`Adding new order ${newOrder}`);   DB.save(newOrder);   Mailer.sendMail(newOrder.assignee, `A new order was places ${newOrder}`);   return {approved: true}; } it("Test addNewOrder, don't use such test names", () => {   addNewOrder({asignee: "John@mailer.com",price: 120}); });//    100%, ,   ,     

Enfoque correcto


Aquí está el informe de prueba de mutación generado por la biblioteca Stryker. Le permite averiguar cuánto código no se prueba (esto se indica por el número de "mutantes" "supervivientes").


Informe Stryker

Los resultados de este informe permiten con más confianza que los indicadores habituales de cobertura de código con pruebas decir que las pruebas funcionan como se esperaba.

  • Una mutación es un código que ha sido modificado deliberadamente por la biblioteca Stryker para probar la efectividad de una prueba.
  • El número de "mutantes" "muertos" (muertos) muestra el número de defectos de código creados intencionalmente ("mutantes") que se identificaron durante las pruebas.
  • El número de "mutantes" "sobrevividos" (sobrevividos) le permite averiguar cuántos defectos de código no han encontrado las pruebas.

Sección 4. Integración continua, otros indicadores de calidad del código


▍ 22. Aproveche las capacidades de linter e interrumpa el proceso de compilación del proyecto cuando detecte problemas que informan


Recomendaciones


Hoy en día, las linters son herramientas poderosas que pueden identificar serios problemas de código. Se recomienda, además de algunas reglas básicas de enlace (como las implementadas por los complementos eslint-plugin-standard y eslint-config-airbnb ), use reglas especializadas. Por ejemplo, estas son las reglas implementadas por medio del complemento eslint-plugin-chai-expect para verificar la corrección del código de prueba, estas son las reglas del complemento eslint-plugin-promise que controlan el trabajo con promesas, estas son las reglas de eslint-plugin-security que verifican la disponibilidad del código Contiene expresiones regulares peligrosas. Aquí también puede mencionar el complemento eslint-plugin-you-dont-need-lodash-underscore , que le permite encontrar en el código el uso de métodos de bibliotecas externas que tienen análogos en JavaScript puro.

Consecuencias de la desviación de las recomendaciones


Ha llegado un día lluvioso, el proyecto presenta fallas continuas en la producción y no hay información sobre las pilas de errores en los registros. Que paso Al final resultó que, lo que arroja el código como una excepción no es realmente un objeto de error. Como resultado, la información sobre la pila no ingresa a los registros. De hecho, en tal situación, el programador puede matar contra la pared o, mucho mejor, pasar 5 minutos configurando el linter, lo que detectará fácilmente el problema y asegurará al proyecto de problemas similares que puedan surgir en el futuro.

Enfoque equivocado


Aquí está el código que, sin darse cuenta, arroja un objeto ordinario como una excepción, mientras que aquí necesita un objeto de tipo Error . De lo contrario, los datos sobre la pila no entrarán en el registro. ESLint encuentra lo que podría causar problemas de producción, ayudando a evitar estos problemas.


ESLint te ayuda a encontrar un error en tu código

▍23. Comentarios más rápidos con los desarrolladores que utilizan la integración continua local


Recomendaciones


¿Usando un sistema centralizado de integración continua, que ayuda a controlar la calidad del código, probándolo, usando el linter, verificando si hay vulnerabilidades? Si es así, asegúrese de que los desarrolladores puedan ejecutar este sistema localmente. Esto les permitirá verificar instantáneamente su código, lo que acelera los comentarios y reduce el tiempo de desarrollo del proyecto. ¿Por qué es esto así? Un proceso de desarrollo y prueba efectivo implica muchas operaciones repetidas cíclicamente. Se prueba el código, luego el desarrollador recibe un informe, luego, si es necesario, se refactoriza el código, después de lo cual todo se repite. Cuanto más rápido funcione el ciclo de retroalimentación, más rápido recibirán los desarrolladores informes sobre las pruebas de código, más iteraciones de mejora de este código podrán realizar. Si lleva mucho tiempo obtener un informe de prueba, esto puede conducir a una mala calidad del código. Digamos que alguien estaba trabajando en algún módulo, luego comenzó a trabajar en otra cosa, luego recibió un informe sobre el módulo, que indica que el módulo debe mejorarse. Sin embargo, ya ocupado en asuntos completamente diferentes, el desarrollador no prestará suficiente atención al módulo del problema.

Algunos proveedores de soluciones de CI (digamos que esto se aplica a CircleCI ) le permiten ejecutar la canalización de CI localmente. Algunas herramientas pagas, como Wallaby.js (el autor señala que no está conectado con este proyecto), pueden obtener rápidamente información valiosa sobre la calidad del código. Además, el desarrollador puede simplemente agregar el script npm apropiado a package.json , que realiza comprobaciones de la calidad del código (pruebas, análisis con un linter, busca vulnerabilidades) e incluso utiliza el paquete concurrente para acelerar las comprobaciones. Ahora, para verificar exhaustivamente el código, será suficiente ejecutar un solo comando, como npm run quality , e inmediatamente obtener un informe. Además, si las pruebas de código indican que tiene problemas, puede cancelar las confirmaciones utilizando git hooks (la biblioteca husky puede ser útil para resolver este problema).

Consecuencias de la desviación de las recomendaciones


Si un desarrollador recibe un informe sobre la calidad del código un día después de escribir este código, es probable que dicho informe se convierta en algo así como un documento formal, y las pruebas de código se divorciarán del trabajo y no se convertirán en su parte natural.

Enfoque correcto


Aquí hay un script npm que verifica la calidad del código. La realización de comprobaciones está paralela. El script se ejecuta al intentar enviar un nuevo código al repositorio. Además, el desarrollador puede lanzarlo por su propia iniciativa.

 "scripts": {   "inspect:sanity-testing": "mocha **/**--test.js --grep \"sanity\"",   "inspect:lint": "eslint .",   "inspect:vulnerabilities": "npm audit",   "inspect:license": "license-checker --failOn GPLv2",   "inspect:complexity": "plato .",     "inspect:all": "concurrently -c \"bgBlue.bold,bgMagenta.bold,yellow\" \"npm:inspect:quick-testing\" \"npm:inspect:lint\" \"npm:inspect:vulnerabilities\" \"npm:inspect:license\"" }, "husky": {   "hooks": {     "precommit": "npm run inspect:all",     "prepush": "npm run inspect:all"   } } 

▍24. Realice pruebas de extremo a extremo en un entorno de producción realista.


Recomendaciones


En el vasto ecosistema de Kubernetes, todavía existe un consenso para usar herramientas que sean adecuadas para implementar entornos locales, aunque tales herramientas aparecen con bastante frecuencia. Un enfoque posible aquí es ejecutar un Kubernetes "minimizado" utilizando herramientas como Minikube o MicroK8 , que le permiten crear entornos livianos que se parecen a los reales. Otro enfoque es probar proyectos en un entorno Kubernetes "real" remoto. Algunos proveedores de CI (como Codefresh ) permiten interactuar con los entornos integrados de Kubernetes, lo que simplifica el trabajo de las canalizaciones de CI al probar proyectos del mundo real. Otros le permiten trabajar con entornos remotos de Kubernetes.

Consecuencias de la desviación de las recomendaciones


El uso de diversas tecnologías en la producción y las pruebas requiere el soporte de dos modelos de desarrollo y conduce a la separación de equipos de programadores y especialistas de DevOps.

Enfoque correcto


Aquí hay un ejemplo de una cadena de CI, que, como dicen, sobre la marcha crea un clúster de Kubernetes (esto se toma de aquí ).

 deploy: stage: deploy image: registry.gitlab.com/gitlab-examples/kubernetes-deploy script: - ./configureCluster.sh $KUBE_CA_PEM_FILE $KUBE_URL $KUBE_TOKEN - kubectl create ns $NAMESPACE - kubectl create secret -n $NAMESPACE docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_REGISTRY_USER" --docker-password="$CI_REGISTRY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" - mkdir .generated - echo "$CI_BUILD_REF_NAME-$CI_BUILD_REF" - sed -e "s/TAG/$CI_BUILD_REF_NAME-$CI_BUILD_REF/g" templates/deals.yaml | tee ".generated/deals.yaml" - kubectl apply --namespace $NAMESPACE -f .generated/deals.yaml - kubectl apply --namespace $NAMESPACE -f templates/my-sock-shop.yaml environment: name: test-for-ci 

▍25. Esforzarse por paralelizar la ejecución de la prueba


Recomendaciones


Si el sistema de prueba está bien organizado, se convertirá en su fiel amigo, listo las 24 horas para informar problemas con el código. Para hacer esto, las pruebas deben realizarse muy rápidamente. En la práctica, resulta que la ejecución en pruebas de 500 unidades en modo de subproceso único que utilizan el procesador de forma intensiva lleva demasiado tiempo. Y tales pruebas deben realizarse con bastante frecuencia. Afortunadamente, las herramientas modernas para ejecutar pruebas ( Jest , AVA , una extensión para Mocha ) y las plataformas CI pueden ejecutar pruebas en paralelo utilizando varios procesos, lo que puede mejorar significativamente la velocidad de recepción de informes de prueba. Algunas plataformas de CI incluso saben cómo paralelizar las pruebas entre contenedores, lo que mejora aún más el ciclo de retroalimentación. Para paralelizar con éxito la ejecución de pruebas, locales o remotas, las pruebas no deberían depender unas de otras. Las pruebas independientes se pueden ejecutar en diferentes procesos sin problemas.

Consecuencias de la desviación de las recomendaciones


Obtener resultados de la prueba una hora después de enviar el código al repositorio mientras trabaja en nuevas características del proyecto es una excelente manera de reducir la utilidad de los resultados de la prueba.

Enfoque correcto


Gracias a la ejecución paralela de pruebas, la biblioteca mocha-parallel-test y el marco Jest omiten fácilmente a Mocha ( esta es la fuente de esta información).


Prueba de herramientas de prueba de rendimiento

▍26. Protéjase de problemas legales mediante el uso de verificación de licencia y verificación de código de plagio


Recomendaciones


Quizás ahora no esté particularmente preocupado por los problemas con la ley y el plagio. Sin embargo, ¿por qué no verificas tu proyecto en busca de problemas similares? Hay muchas herramientas disponibles para organizar tales inspecciones. Por ejemplo, estos son el verificador de licencias y el verificador de plagio (este es un paquete comercial, pero existe la posibilidad de su uso gratuito). Es fácil integrar dichos controles en la canalización de CI y verificar el proyecto, por ejemplo, para dependencias con licencias limitadas, o para la presencia de código copiado de StackOverflow y probablemente infringiendo los derechos de autor de otra persona.

Consecuencias de la desviación de las recomendaciones


El desarrollador, sin darse cuenta, puede usar el paquete con una licencia que no es adecuada para su proyecto, o copiar el código comercial, lo que puede generar problemas legales.

Enfoque correcto


Instale el paquete del verificador de licencias localmente o en un entorno CI:

 npm install -g license-checker 

Comprobaremos las licencias con él, y si encuentra algo que no nos conviene, reconoceremos que el cheque no tuvo éxito. El sistema CI, al detectar que algo salió mal al verificar las licencias, detendrá el ensamblaje del proyecto.

 license-checker --summary --failOn BSD 


Comprobación de licencia

▍27. Compruebe constantemente el proyecto para detectar dependencias vulnerables


Recomendaciones


Incluso los paquetes altamente respetados y confiables, como Express, tienen vulnerabilidades. Para identificar tales vulnerabilidades, puede usar herramientas especiales, como la herramienta estándar para auditar paquetes npm o el proyecto comercial snyk , que tiene una versión gratuita. Estas comprobaciones, junto con otras, pueden formar parte de la canalización de CI.

Consecuencias de la desviación de las recomendaciones.


Para proteger su proyecto de las vulnerabilidades de sus dependencias sin utilizar herramientas especiales, deberá monitorear constantemente las publicaciones sobre dichas vulnerabilidades. Esta es una tarea que consume mucho tiempo.

Enfoque correcto


Aquí están los resultados de la verificación del proyecto usando NPM Audit.


Informe del paquete de verificación de vulnerabilidad

▍28. Automatizar actualizaciones de dependencia


Recomendaciones


El camino al infierno está pavimentado de buenas intenciones. Esta idea es totalmente aplicable al package-lock.json , cuyo uso, por defecto, bloquea las actualizaciones de paquetes. Esto sucede incluso en los casos en los que los npm install y npm update proyectos a un estado saludable. Esto lleva, en el mejor de los casos, al uso de paquetes obsoletos o, en el peor, a la aparición de código vulnerable en el proyecto. Como resultado, los equipos de desarrollo confían en la actualización manual de información sobre versiones adecuadas de paquetes o en utilidades como ncu , que, nuevamente, se lanzan manualmente. El proceso de actualización de dependencias se automatiza mejor, centrándose en el uso de las versiones más confiables de los paquetes utilizados en el proyecto. Esta no es la única solución correcta, sin embargo, al automatizar las actualizaciones de paquetes, hay un par de enfoques notables. El primero es inyectar algo como verificar paquetes usando npm-outdated o npm-check-updates (ncu) en la tubería de CI. Esto ayudará a identificar paquetes obsoletos y animará a los desarrolladores a actualizarlos. El segundo enfoque es utilizar herramientas comerciales que verifican el código y realizan automáticamente solicitudes de extracción destinadas a actualizar las dependencias. En el campo de la actualización automática de dependencias, nos enfrentamos a otra pregunta interesante con respecto a la política de actualización. Si se actualiza con cada nuevo parche, la actualización puede poner demasiado estrés en el sistema. Si actualiza inmediatamente después del lanzamiento de la próxima versión principal del paquete, esto puede conducir al uso de soluciones inestables en el proyecto (las vulnerabilidades en muchos paquetes se encuentran en los primeros días después del lanzamiento, lea sobre el incidente con eslint-scope). « », , . , 1.3.1, 1.3.2, 1.3.8.


, , , .


ncu , , , .


ncu

▍29. , Node.js



, Node.js-, , Node.js .

  1. . — , , , Jenkins .
  2. , Docker.
  3. . , , . (, ), , , , .
  4. , , , . — , , , .
  5. , . , feature, — master, , ( ).
  6. . , .
  7. .
  8. (, Docker) .
  9. , , , . , node_modules .


, , .

▍30.



, . , , , Node.js , . CI-, , « ». , , , . , , mySQL, — Postgres. , Node.js, — 8, 9 10. , . CI-.


, , , . , , .


CI- Travis Node.js.

 language: node_js node_js: - "7" - "6" - "5" - "4" install: - npm install script: - npm run test 

Resumen


, , . , , .

Estimados lectores! ?

Source: https://habr.com/ru/post/es435464/


All Articles