Si cambiamos el código, necesitamos cambiar las pruebas, de lo contrario se volverían obsoletas, pero no lo hacen, porque es una documentación en vivo. Pero ¿cómo sabemos y verificamos si nuestro programa está haciendo lo que se espera que haga? ¿Cómo podemos verificar la calidad de esta retroalimentación? Y aquí no voy a hablar del 100% de cobertura.
Así que empecemos con la precisión. Si tus pruebas fallan, ¿puedes determinar exactamente qué parte del código ha fallado? ¿Cuánto tiempo te lleva saber dónde falló? Así que lo que queremos aquí son funciones realmente granulares, cuanto más granulares sean, más precisión se puede obtener. Por lo tanto, es mucho más rápido si tienes funciones pequeñas sin dependencias del mundo exterior, así que recuerda las funciones puras.
También se trata de velocidad. Cuanto más rápido encontremos una prueba fallida, antes podremos identificar el problema y menor será su impacto. Así que lo que necesitamos aquí son pruebas que sean simples de escribir y mantener, y también que sean rápidas de ejecutar. Si tenemos mucho código complejo con muchas dependencias del mundo exterior, nos llevará mucho tiempo mantener estas pruebas. Y también necesitamos pruebas que sean confiables. Necesitamos confiar en el resultado de nuestras pruebas. Si el resultado cambia de una ejecución a otra, si no cambiamos el código, las configuraciones o las dependencias, ¿por qué mantener este tipo de pruebas? Porque no confiamos en ellas, así que no tiene sentido mantenerlas.
Aquí generalmente estamos hablando de pruebas de extremo a extremo. Las pruebas de extremo a extremo son un problema porque no caminas nada, realmente guardas cosas en la base de datos. Es muy común que fallen por razones oscuras, como la latencia, la recolección de basura, operaciones asíncronas. Así que necesitamos pensar de manera diferente. Aquí necesitamos pensar un poco más grande. Sabemos que las pruebas unitarias cubren los niveles de función, las pruebas de integración cubren los flujos, y necesitamos garantizar que la conversación entre los servicios funcione. Por lo general, usamos las pruebas de extremo a extremo para eso, pero podemos pensar un poco más grande y probar la conversación entre dos servicios a la vez, por ejemplo. Así que aquí usamos pruebas de contrato.
Cada prueba de contrato va a tener un servicio proveedor y un servicio consumidor, y para cada comunicación entre ellos, necesitamos definir una interfaz clara llamada contrato. Así que ahora tenemos pruebas automatizadas que aseguran que los datos generados por el proveedor pueden ser consumidos por el consumidor. Y si cambiamos algo, el contrato se romperá. Así que es importante tener en cuenta que esto no es un reemplazo uno a uno de las pruebas de extremo a extremo, pero la mayoría de los errores que las pruebas de extremo a extremo capturan, estas pruebas también pueden capturarlos. Así que con eso, podemos tener precisión, velocidad y confiabilidad. Y eso es lo que queremos.
Ahora, voy a hablar sobre cómo diseñar un registro. Porque está bien, tenemos la programación funcional, tenemos las pruebas, pero ¿cómo diseñar el código para aprovechar esto? Lo que queremos es una alta mantenibilidad con una baja deuda técnica, porque queremos que las aplicaciones que se utilizan para realizar mantenimiento tengan una baja deuda técnica. Necesitamos que sean simples y fáciles de trabajar. Y esto es difícil porque la mantenibilidad es un concepto a largo plazo porque al principio, es realmente fácil.
Comments