Cosas a considerar cuando se prueba unitariamente una interfaz

¡Hola, Habr!



Nos gustaría llamar su atención sobre una novedad más disponible en nuestro pedido anticipado: un libro sobre pruebas unitarias .







El autor de la publicación de hoy habla breve y claramente sobre las ventajas de las pruebas unitarias y TDD usando el front-end como ejemplo.



¡Disfruta leyendo!



Las pruebas unitarias son uno de los enfoques más importantes que todo desarrollador debe tomar. Sin embargo, he visto muchos proyectos en los que puede ser difícil poner en práctica las pruebas unitarias. Hay un número de razones para esto. Por ejemplo, alguien podría decir que debe concentrarse en desarrollar funciones, y escribir pruebas unitarias en este caso es una carga adicional seria. Otros notarán que probar su código no es trivial porque el código en sí es complejo. En ambos casos, se pierde el punto.

Recuerdo esta expresión: cuando piense si tiene tiempo para escribir pruebas unitarias, piense si tendrá tiempo adicional para procesar el mismo código dos veces, debido a errores y problemas que surgirán en él.

Escribir código comprobable



Primero, definamos qué errores comunes hacen que probar su código sea más difícil. Cuando se trata de pruebas de front-end, uno de los problemas más difíciles que conozco es probar los componentes de la interfaz de usuario. El principal problema que encontré en este caso es el siguiente: sucede que los componentes son demasiado "inteligentes" y tienen dependencias de otros fragmentos de código, por ejemplo, de llamadas a API, carga de datos, manejo de eventos e implementación de lógica empresarial. A muchos desarrolladores no les gusta escribir pruebas para componentes tan "pesados".



La solución más simple a este problema es separar los componentes en lógica y presentación. Con esta separación, puede probar cómo los componentes de la presentación se adhieren a la lógica de presentación, realizar el procesamiento y la representación de eventos y centrarse por separado en probar la lógica empresarial en los componentes responsables de la lógica.

Asegurarse de que sus componentes sean probables también es una buena manera de asegurarse de que sean independientes, reutilizables y convenientes de usar juntos. Esto es absolutamente necesario, especialmente cuando se comparten componentes entre proyectos utilizando herramientas y plataformas populares como Bit ( Github). Por lo general, Bit mostrará y probará cada uno de sus componentes por separado, y solo luego los enviará a una colección compartida, asegurando así que sean realmente reutilizables; de lo contrario, ¿cuál es el punto de hacerlos separables?







Ejemplo: exploración de componentes React reutilizables compartidos en Bit.dev



Un círculo vicioso: que pasa si no escribes pruebas unitarias



Según mi experiencia con equipos que no aplican las pruebas unitarias correctamente (es decir, que no usan la cobertura de la prueba como métrica), comencé las pruebas unitarias demasiado tarde o desde el principio, pero no aprendí a practicarlas. Puede haber muchas razones para esto, pero le daré algunos ejemplos para que le sea más fácil decidir cuál se parece más a su caso.



Cómo probamos nuestro código durante el desarrollo



En mi opinión, a menos que se ciña al desarrollo basado en pruebas (TDD), la funcionalidad se puede desarrollar siempre que la interfaz se cargue constantemente en el navegador. Debe concentrarse en visualizar la funcionalidad y las interacciones que tienen lugar en la interfaz de usuario, ya que esta es la esencia del desarrollo del lado del cliente.



Solo después de eso, cuando toda la funcionalidad ya está funcionando, el énfasis cambia a las pruebas unitarias.



Este es el principal problema al que debe enfrentarse: escribir pruebas unitarias es un trabajo adicional que se realiza una vez que se completa el desarrollo de la funcionalidad. Este enfoque da la impresión de que las pruebas unitarias son una tarea adicional que se realiza además del desarrollo de la funcionalidad lista para usar.



Debido a esta formulación de la pregunta, tanto los propietarios de productos como los desarrolladores clasifican las pruebas unitarias como un costo.



Pero si se apega a TDD, todo se desarrolla exactamente al revés. Dado que los casos de prueba se escriben con anticipación, no necesitamos verificar todo visualizando constantemente los cambios, porque tenemos una forma diferente de verificar el código durante el desarrollo. En este caso, la herramienta de verificación principal es escribir código que pasará el caso de prueba de la unidad.



Por tanto, creo que la práctica de TDD es la etapa más importante antes de la práctica de pruebas unitarias.



Con qué frecuencia se ejecutan las pruebas unitarias



Quizás se pregunte cómo la ejecución de una prueba unitaria afecta la forma en que se escriben las pruebas unitarias. Por ejemplo, digamos que tiene un conjunto completo de pruebas. Lo desterras de vez en cuando. Por lo tanto, los desarrolladores rara vez se convencen de su utilidad. Además, incluso en los casos en los que la prueba falla, es demasiado tarde.

Por lo tanto, es importante ejecutar pruebas unitarias al menos en cada etapa de la compilación de la solicitud de extracción. Al adherirnos a esta práctica, tomada de DevOps, nos aseguramos de que cada nuevo bloque de código que agreguemos pase un conjunto de pruebas unitarias. Incluso si existe la necesidad de cambiar un caso específico, el desarrollador lo hará antes de que actúe la fusión de código.



Con qué frecuencia medir la cobertura del código mediante pruebas



Al igual que con la ejecución de pruebas, esta medición también es importante tanto psicológicamente como como práctica para que los desarrolladores juzguen si preparan suficientes casos de prueba para cubrir todo el código escrito.

En este caso, creo que el panel por sí solo no es suficiente, en el que se puede ver la cobertura de las pruebas unitarias. Pero, si fuera posible agregar un acto de medición al agregar un nuevo código y así verificar el nivel de cobertura de la prueba, entonces tal alternativa sería más conveniente para obtener retroalimentación instantánea. Incluso podríamos formular reglas que requieran que cualquier código nuevo agregado a la base de datos sea cubierto por pruebas, digamos, 80%. Es más apropiado agregar esta validación al proceso de compilación de la solicitud de extracción.



Dado que los desarrolladores reciben comentarios instantáneos sobre la cobertura de prueba unitaria de su código, son libres de tomar medidas para ponerse al día con dicha cobertura según sea necesario.



Salir de este círculo



Si ya está involucrado en este círculo vicioso, entonces la mejor manera de salir de él es reforzar las prácticas discutidas anteriormente. Dado que lo anterior se refería a pruebas frecuentes para validar el código recién agregado, así como a probar la cobertura de código nuevo, puede desarrollar un procedimiento que sea adecuado para cualquier operación de agregar o cambiar código.

Es muy poco probable que tenga tiempo suficiente para cubrir todo el código antiguo con pruebas (a menos que el proyecto en sí sea completamente nuevo) de inmediato, antes de tener que escribir código nuevo. Por tanto, no cuentes con ello para nada, porque desde un punto de vista empresarial, no es práctico.
Mientras tanto, puede realizar mediciones periódicas, cubriendo estratégicamente ciertas partes del código antiguo con pruebas. Lo más importante es que debe capacitar a todos los desarrolladores para que sigan esta práctica. Es igualmente importante desaprender cómo considerar este trabajo como costos y transmitir a todos los propietarios del proyecto lo importante que es escribir pruebas unitarias. De lo contrario, muchos, especialmente los que no son técnicos, pueden pensar que las pruebas unitarias son un trabajo adicional, en lugar del cual uno podría dedicar tiempo a desarrollar nuevas funciones.



Entonces, ¿cuál es el verdadero valor de todo este trabajo?



Las pruebas unitarias son útiles de muchas formas. Si se aplican correctamente, ayudan a reducir la cantidad de defectos en el código, actúan como un seguro cuando se prueba la funcionalidad existente, no se dañan al refactorizar el código y también ayudan a mantener la productividad general en un alto nivel.

Al observar el código, que está bien cubierto por las pruebas unitarias, todos pueden ver qué tan seguro se ve.
Así que llenemos las lagunas y volvamos a la pista adoptando las prácticas de DevOps y acostumbrándonos a escribir buenas pruebas unitarias y al mismo tiempo ceñirnos al desarrollo basado en pruebas.



All Articles