Saltar al contenido principal
Página

Tema 3.2 - Métricas de calidad para pruebas unitarias

Linters (Sonarlint)

Antes que nada, los Linters son herramientas que realizan tareas para detectar y solucionar problemas de calidad de código en cualquier lenguaje de programación; anteriormente solo se detectaba código sospechoso y confuso entre diferentes arquitecturas en programas escritos en C.

Su funcionamiento se basa en realizar un análisis estático del código. Uno de los linters para trabajar con los IDE de Eclipse, IntelliJ DEA, Visual Studio y VS Code, es Sonarlint, que detecta los problemas de calidad y seguridad en lenguajes de programación como Java, JavaScript, Python, PHP y HTML5.

Para la instalación y configuración del IDE Eclipse, damos click a “Help” y “Eclipse Marketplace”

Instrucciones para descargar Sonarlint


Luego de lo anterior, se abrirá la siguiente ventana, donde se debe digitar la palabra “Sonarlint” en el espacio de Search y dar clic en buscar. Finalmente, se da clic en install y se aceptan los términos de la licencia y el IDE se encargará de realizar la descarga de la extensión.

Instrucciones para descargar Sonarlint


Una vez finalizado el proceso de descarga, la extensión ya se encuentra en nuestro IDE. Para ejecutarla, simplemente seleccionamos un proyecto, damos clic derecho sobre este, luego la opción SonarLint y finalmente Analyze.

Para nuestro ejemplo, utilizaremos la clase ServicioCalculadoraImplementacion del ejercicio de fake.

Ejecución de Sonarlint


Automáticamente, la extensión empezará a buscar los errores y recomendaciones que puede dar respecto a nuestro código. Nos mostrará la siguiente ventana, en la cual estará la fuente del error y la descripción. En este caso, nos sugieren declarar x2 en una línea por separado y el return de algunos métodos debe contener la operación sin pasarla como resultado por una variable.

Resultado tras ejecutar sonarlint


Si damos doble clic sobre alguna de las descripciones nos redireccionará al código que debemos corregir. Si observamos, en la línea donde se encuentra este código, double raizCuadrada = Math.sqrt (numero); la clase Math y su método están subrayados, indicándonos que esta debería ir directamente en el return del método. Además de mostrarnos el error, nos da un ejemplo de cómo debería manejarse la situación, lo cual facilita la aplicación de las sugerencias brindadas.


ejemplo


Al corregir todos los errores tendríamos el siguiente código y solo nos bastaría ejecutar de nuevo Sonarlint.

corrección


Note que sonarlint, ya no nos muestra ningún error o sugerencia respecto a nuestro código. Con esto damos por terminado la presentación de esta herramienta tan útil al momento de dar seguridad y manejar calidad en nuestros desarrollos.

Ejecución de Sonarlint  para verificar que se hayan tomado las sugerencias dadas


Cobertura de pruebas unitarias

La cobertura de código es un factor primordial al momento de realizar nuestras pruebas unitarias, puesto que este nos indica la cantidad de código que está siendo probado, por lo que la cobertura es directamente proporcional al código en prueba.

Una cobertura con un porcentaje mayor al 70% se categoriza como una cobertura de alta calidad, mientras que una que esté entre 50% y 69% se considera de calidad media, así mismo una que este entre 20% y 49% es una cobertura baja y las menores al 20% son consideradas como coberturas no razonables, por lo que se debe considerar la forma como se está enfocando en hacer los test.

Existe gran variedad de herramientas, claramente condicionadas a factores como lenguaje de programación y entorno de desarrollo,  nos permiten hacer el análisis de cobertura a nuestras pruebas unitarias, entre ellas OpenCover.UI, SonarQube, Cobertura y EclEmma; esta última disponible para el IDE eclipse, la cual utilizaremos como medio para hacer nuestros cálculos.

A modo de presentación de EclEmma, podemos afirmar que es una herramienta de cobertura de código Java,  gratuita para el IDE eclipse. Después de ser ejecutada, la información estará disponible en el entorno de trabajo  con la descripción general de la cobertura y el resultado de fuente, que nos permitirá conocer que parte de nuestro código es total, parcial o no cubierto por las pruebas.

Su instalación en Eclipse es bastante sencilla, pero antes de ejecutarla debemos cerciorarnos si ya existe, en caso de estar incluida en nuestro IDE,  se mostrará en la barra superior de herramientas.

Verificación de si se tiene instalado eclemma


Sin embargo, si no está incluida en eclipse, tenemos al menos dos opciones para obtener la extensión. La primera es por medio de la opción “Eclipse Marketplace”, buscando EclEmma e instalándola como se hizo con SonarLint.; y la segunda es a través de la opción “Install New Software…” ubicada en help.

Instalación de Eclemma


Pegamos la siguiente url http://update.eclemma.org/, luego damos clic en  adicionar, ponemos un nombre pertinente y oprimimos el boton de "aceptar".

Instalación de Eclemma


Cuando hayamos completado la instalación, tendremos una nueva opción en nuestro IDE,  para ejecutarlo tendremos que usar la opción “Coverage as” y ejecutarlo normalmente con JUnit.  A manera de explicación retomaremos el ejercicio planteado en el apartado de pruebas unitarias, el cual nombramos como “SistemaBasicoNotas” y si se desea, se añaden nuevas pruebas a las clases.

Ejecución de eclemma en el proyecto sistemaBasicoNotas


Una vez ejecutado, JUnit mostrará normalmente la ventana de resultados y adicional se nos abrirá otra ventana llamada coverage, en la cual vemos como está la cobertura en nuestras pruebas unitarias. En  coverage podremos desplegar todo el proyecto y se nos mostrará por cada clase el porcentaje, el valor de cobertura y de instrucciones, las pérdidas y el total de instrucciones, además a modo de ilustración nuestro código estará coloreado de verde (cubierto) y rojo (no cubierto). En nuestro ejemplo, podemos notar que, en total, tenemos una cobertura del 92.9%, lo que indica que el código está catalogado en este aspecto como alta calidad, según los porcentajes descritos al inicio del tema. Es de aclarar, que en muchos de los casos, no podemos asegurar una cobertura de pruebas del 100%, puesto que existen clases muy planas a las cuales no es posible aplicarle cualquier tipo de prueba.

Resultados de eclemma


Deuda Técnica

La deuda técnica es un eufemismo que comenzó en el desarrollo décadas atrás y es muy conocido en la actualidad. Indica la cantidad de trabajo adicional que se acumula cuando se implementa código pobre, incumpliendo las buenas prácticas en el desarrollo de Software, cuya causa principal es la de recortar tiempos de entrega. En pocas palabras, es algo que resta valor al producto software. 

La deuda técnica se ve reflejada en una documentación escasa o incompleta, errores, ausencia en el control de versiones, arquitecturas no escalables o con un grado de escalabilidad muy pobre y en la rigidez para actualizar el sistema a las nuevas tecnologías; todo ello como resultado de errores conocidos que no se solucionan, falta de implementación de mejoras en el código fuente y aplicación de pruebas insuficientes que desencadena una baja calidad.

Entre lo que se considera causas de la deuda técnica están:

  • Falta de planificación: Un ejemplo de ello es iniciar el desarrollo antes de completar el diseño del proyecto para ahorrar tiempo, lo que podría provocar volver al inicio más tarde.
  • Presiones del negocio:  Se refiere a la forma cómo la sociedad evoluciona a gran velocidad y la manera como los productos deben estar listos cuanto antes, dejando de lado el correcto análisis del desarrollo en lo que respecta a control de calidad y cambios rápidos.
  • Cambios en la especificación: Hace hincapié a la manera como los cambios de las especificaciones se dan en el proceso de desarrollo en las etapas finales.
  • Falta de buenas prácticas
  • Falta de conocimiento por parte del equipo de trabajo
  • Falta de colaboración: Esta causa se refiere a como los desarrolladores y los dueños del negocio trabajan poco de la mano, lo que causa una toma de decisiones errada por parte del equipo de desarrollo a falta del conocimiento de cómo es el funcionamiento del negocio.
  • Liderazgo deficiente: La falta de propiedad hasta un liderazgo deficiente son causas potenciales de la deuda.

La deuda técnica es similar a tener un crédito con el banco a una tasa de interés alta, entre más tiempo pase, más interés se pagará; por lo cual es importante darle una gestión pertinente y para ello es necesario el esfuerzo coordinado de tres partes.

  • El equipo de desarrollo debe trabajar con los responsables técnicos para dibujar una hoja de ruta para resolver los problemas principales
  •  En caso de estar trabajando bajo una metodología de desarrollo ágil como SCRUM, el product Owner debe comprender que resolver los problemas supone entregar software a un menor ritmo.
  • Los stakeholders deben entender a través del trabajo con los dos anteriores a que los gastos en resolver una deuda técnica no es un gasto, sino una inversión que facilitará y recudirá muchos riesgos asociados al proyecto.

Pese a que las herramientas de calidad de código no son suficientes para la identificación de la deuda técnica, ya que en ciertos casos ésta no se relaciona con código y sus cualidades intrínsecas, sino a términos de estructura, arquitectura o brechas digitales; implementar algunas de ellas ayudara a identificar una cantidad de elementos asociados a la deuda. Algunas herramientas como SonarQube ayudaran a medir los posibles problemas del código midiendo la calidad del este desde la facilidad de lectura, complejidad ciclomática, complejidad npath y normas al momento de escribir código. Ayudará además, usar integración continua como Jenkins o Travis desplegando código integrado y medido. Otros puntos importantes para evitar la deuda técnica son

  • Concientizar a las personas sobre esta para que se ofrezca un flujo de información más maduro y se pueda tratar los errores que se presenten.
  • Realizar en el equipo un seguimiento de la deuda técnica mientras se realizan las tareas
  • No pedir a los equipos que hagan demasiado en corto tiempo
  • Usar los KPI (Indicadores de calidad) para rastrear las expectativas del proyecto
  • Capacitar a los equipos para planificar alrededor de la deuda

En la siguiente imagen se podrá apreciar los cuatro cuadrantes desarrollado por Martin Fowler, donde se constata cuatro tipos de posibles mejoras o tareas para aumentar el valor del producto software.

Cuadrantes de Martin Fowler


Código Duplicado

Pensar en este tipo de situaciones, nos traslada al principio DRY o Don´t Repeat Yourself, un pilar innegociable en el imaginario colectivo de los programadores, por lo que repetir es malo y reutilizar es bueno. No obstante, esto no es del todo cierto y reutilizar código en algunas condiciones puede crear más problemas, que ventajas; por lo que saber elegir cuándo reutilizar código es un tema importante llevándonos a considerar los dos tipos de duplicidad:

  • El primero es la duplicidad real, donde el código es idéntico y sirve para lo mismo; este tipo de código es el que se debe unificar.
  • El segundo es la duplicidad accidental, en la que el código puede parecer el mismo, pero sirve para cosas distintas, siendo este el código que debemos evitar unificar.

Pero ¿cuándo debemos utilizar el real o accidental? La respuesta es, partiendo de la siguiente idea, si los componentes que utiliza nuestra clase unificada representan varios conceptos diferentes y esto no les impide evolucionar por su propio camino.

Ahora bien, es importante tener claro las razones de por qué se debe evitar el código duplicado:

  • Primero porque aumenta innecesariamente el número de líneas de código, siendo complejo su mantenimiento.
  • Segundo, implica que si hay que cambiar ese código repetido se debe cambiar en muchos sitios, lo que provoca una baja productividad y aumenta la probabilidad de error.
  • Tercero, el código duplicado esconde un problema en la falta de diseño de software. Como consecuencia de tener código, así aumentaría la deuda técnica, las pruebas unitarias, código para documentar y el incumplimiento de una cantidad de reglas.

El análisis de código duplicado, permite encontrar bloques duplicados en el código fuente. La presencia de este tipo de situaciones, como ya se había dicho, indica malas prácticas, en caso de requerirse la duplicación de este, la recomendación sería encapsular ese código en un método de una clase, disminuyendo así el tamaño del código y facilitando el mantenimiento.

Una densidad de código duplicado menor a 1% se cataloga como alta calidad, entre 1% y 5% de buena calidad, así mismo entre un 5% y 25% como razonable con intención de corrección y finalmente si la densidad de código supera el 25% no es razonable y debe corregirse inmediatamente. Lo que podría causar cierto grado de preocupación, es encontrar código duplicado en proyectos grandes y posterior realizar los cálculos para saber en qué categorías de densidad de código duplicado se encuentra un proyecto, por suerte, en la actualidad muchas tareas están automatizadas, y esta no es una excepción, habiendo en el mercado cantidad de herramientas que nos facilitan este trabajo. A continuación, algunas herramientas que pueden ser de utilidad: PMD, Check Style, JSCPD, Sonar, CPD, Google CodePro Analytix, SonarQube, Simian.

Nota: Las herramientas nombradas, realizan un control desde el punto de vista del estudio estático y de caja blanca.

Code Smell

En programación, un code smell es conocido como un código que huele o apesta, lo que indica que las cosas no se están haciendo como se debe, trayendo implicaciones de cierto grado de complejidad en el futuro. Code Smell no necesariamente tiene por qué ser un bug de programación; indica deficiencias en el diseño y puede causar un desarrollo más lento; finalmente aumenta el riesgo de errores o fallo a futuro.

Si bien el code smell no impide que el programa deje de funcionar, si se representa como deficiencia en el diseño que puede ralentizar el desarrollo o aumentar el riesgo de errores y fallos futuros. Termina siendo un factor contribuyente a la deuda técnica, algo que como ya sabemos es negativo

Tipos y subtipos de code smells

  • Bloaters: Representan algo que ha crecido desproporcionadamente y resulta ser complejo de entender y manejar. En este grupo se encuentran los métodos grandes, clases grandes (toman muchas responsabilidades dejando de lado el principio de single responsability), Long Parameter List (métodos con muchos parámetros).
  • Object-Orientation Abusers: Son códigos que dan solución a ciertos problemas sin tener en cuenta las muchas posibilidades que ofrece la programación orientada a objetos, como es el caso de usar un Switch en objetos cuando la manera de tratarlo sería haciendo uso del polimorfismo. En este grupo se encuentran los refused bequest (subclases que no utilizan lo que heredan de las superclases), Temporary field (clases que tienen un atributo que solo es utilizado en algunas situaciones, cuando un objeto necesita todos sus atributos).
  • Change preventers: Son smells que previenen el cambio o expansión del software. Se encuentran los divergent change (una clase debe ser continuamente modificada para ajustarse a nuevos ambientes) y shotgun surgery (para cada cambio pequeño en una clase se deben modificar muchas cosas pequeñas en otras).
  • Dispensables: Son innecesarios y su ausencia hace que el código se vea más limpio y sea más eficiente. Algunos de ellos pueden ser data class (clases que solo contienen datos y respectivos accessors para que los utilicen otras clases) y generalidad especulativa (clases, métodos, variables o parámetros sin utilizar).
  • Acopladores: contribuyen un acoplamiento excesivo entre clases. Algunos de ellos como el Feature Envy (objeto interesado más en otros que en sí mismo) y  middle man (ocurre cuando un objeto delega trabajo a otras clases).

En cuanto a herramientas que ayudan a detectar code smell, están: Checkstyle, PMD, FindBugs y SonarLint, algunas ya vistas anteriormente como solución a los temas pasados.


Última modificación: miércoles, 16 de marzo de 2022, 17:07