Tres pilares de las pruebas de unidades

¿Qué es la Unidad?
¿Por qué llamamos a estas pruebas pruebas unitarias? La respuesta es simple – porque probamos solamente una unidad. Muy buena respuesta, pero ¿qué es esta unidad? ¿Método, clase, módulo? La unidad es simplemente la parte más pequeña de su sistema que puede probar. Si piensa en probar algo, piense en probar sólo una parte de él. Si puedes imaginar esto, significa que no era una unidad. Ahora, piense en su parte. ¿Puedes pensar en probar sólo una parte de ella … (Creo que tienes mi punto y si no, lee acerca de la recursión)
¿Qué es la Prueba (Unidad)?
Ok, tenemos lo más pequeño que podemos pensar. Es probablemente un método, tal vez una clase, no importa. Piense en un escenario simple, pero representativo de usarlo. Juguemos con el servicio de “inicio de sesión”. Deje que el escenario simple sea: nombre de usuario correcto y contraseña incorrecta (no estoy diciendo que este debería ser el primer escenario, pero debería ser alguno). La segunda cosa – comportamiento esperado. ¿Qué debe hacer en determinadas circunstancias? Supongamos que debe devolver el mensaje “Contraseña incorrecta”. Y esta es nuestra prueba. Oh, ok, pero ¿cómo conseguimos el usuario que existe en la base de datos? Tenemos que conectar con la base de datos, archivo o cualquier otra cosa. Este es exactamente mi punto: separaciones de preocupaciones, aislamiento. Tenemos que probar nuestro “sistema” de forma aislada. No queremos probar nuestra base de datos; Queremos probar sólo el servicio de “inicio de sesión”. Por lo tanto, tenemos que proporcionar datos falsos (pero sobre falsificaciones, stubs, burlas y aislamiento voy a escribir otra vez) para probar sólo el comportamiento de nuestro servicio.
Primer pilar: Confiabilidad
Las pruebas unitarias deben ser nuestro paracaídas, cuerda de bungee, red de seguridad. Por lo tanto, tenemos que confiar en ellos, de lo contrario son inútiles. Si las pruebas pasan, ¿estás seguro de que significa algo? Quizás sea siempre verde no importa qué o quizá no prueba lo que usted piensa que está probando. Un problema común aparece si cambia o refactoriza algo, ejecuta las pruebas y todos pasan, pero todavía no está seguro si no rompió nada. Pero si usted sigue el ciclo rojo, verde, del refactor, usted puede estar seguro. En primer lugar, usted vio sus pruebas de color rojo (todos ellos) al principio. En segundo lugar, usted sabe que están pasando solamente porque usted realmente escribió un código específico. Por lo tanto, usted está seguro de que si todas las pruebas son de color verde de su módulo está bien. No tienes que comprobarlo de otra manera.

Consejo Si tiene que modificar el código de otra persona (supongamos que hay pruebas :)). En primer lugar, intente algo como esto. Elimine una línea aleatoria (compile, si tiene que) o cambie si / para / while y ejecute pruebas. Si todavía están pasando – es malo para usted. Este paracaídas tiene fugas, mejor no lo use (o haga, pero no se sorprenda si se cae).
Segundo Pilar: Mantenibilidad
Es obvio que las pruebas requieren atención de la misma manera que el código de producción. Si cambia el código de producción (refactor, corregir bug o agregar nueva funcionalidad) algunas de sus pruebas se romperán (significa que ni compilan ni fallan). Es un gran problema. Cuantas más pruebas, más atención necesitan. Podemos reducir el tiempo que pasamos en nutrir mediante la escritura de prueba sólo contra el método público. Los métodos públicos son contratos. Si especificamos algún contrato, preferimos no cambiarlo tan a menudo como los métodos privados. Si usted siente que tiene que probar el método privado es un signo de un mal diseño (se llama “olor de código”). Probablemente la funcionalidad de este método pertenece a otra parte. Lo siguiente que podemos hacer es eliminar la duplicación en las pruebas, mover partes que pueden variar (por ejemplo, construcción, inicialización) en un solo lugar. Puede utilizar el método de fábrica o la “configuración” común para su prueba. Si algunas pruebas en su clase de prueba necesitan “configurar” diferentes que otras, divídelas en dos clases de prueba (sí, dos clases de prueba pueden probar una clase de producción o incluso un método, ¿por qué no?). Las pruebas deben ser refactorizadas con tanta frecuencia como el código de producción.
Tercer pilar: legibilidad
Por último, pero no menos importante, la legibilidad. Dado que las pruebas unitarias son especificaciones ejecutables, debería ser capaz de leerlas como especificaciones. En primer lugar (y creo que el aspecto más importante) es una buena convención de nomenclatura. No puedo decir que la convención que voy a presentar sea la mejor, pero la uso y funciona para mí. Es la misma convención que recomienda Roy Osherove. Aquí está el patrón:
¿Qué estamos esperando en las condiciones que esperaba?
WhatAreWeTesting_InWhatConditions_WhatAreExpectedResult

En primer lugar, ¿por qué es tan importante el nombre de un método? Porque, en todo (hasta donde yo sé) corredor de prueba esta es la primera (y más visible) información sobre la prueba de falla. Si sigues mi guía, no necesitarás nada más. Usted sabrá lo que está mal de inmediato. Ni afirma mensajes ni comentarios necesarios. El nombre del método es todo lo que necesita. No se preocupe por un nombre de método largo. IntelliSense le ayudará, pero en este caso

Usted no lo escribirá dondequiera, así que no hay problema en absoluto. El siguiente aspecto es una sola afirmación en la prueba. Está fuertemente conectado con el nombre de la prueba. Si tiene varias afirmaciones en la prueba, ¿cómo la nombra? Es la primera pista de que algo está mal con su prueba, cuando no se puede nombrar de una manera sencilla. Y si usted tiene una sola afirmación para la prueba, ¿cuál es el propósito de afirmar mensaje? Es obvio por su nombre lo que la prueba está afirmando. Puede haber excepciones a esto, p. Cuando queremos hacer una afirmación sobre un objeto que no ha sobrepasado el método Equals () (pero quizás debería tener?). Recomiendo encarecidamente utilizar el patrón AAA (a.k.a. triple A) para el diseño de la prueba. Representa Arrange, Act, Assert. Esto significa que la prueba debe dividirse en tres partes. La primera parte es Organizar. Aquí están todos los preparativos posibles para la ejecución de la prueba a tener lugar: la inicialización, stubbing, etc La segunda es la Ley. Aquí es donde se invoca el método, que estamos probando. El último es Assert. Este es el lugar para la aserción. Estas partes podrían ser separadas con comentarios como “// arreglar”, etc, pero me di cuenta de que estos no son necesarios. Separo estas partes usando líneas vacías (cada parte no tiene líneas vacías dentro), por lo que cada prueba tiene sólo dos líneas vacías.

Si confías en tus pruebas, las usas con más frecuencia, por lo que escribirás más de ellas. Cuando tienes más pruebas, confías en ellas más (¿ves el ciclo?). Si las pruebas fueran fáciles de mantener, no tendría miedo de escribir más de ellas y no perdería el tiempo en cambiarlas. Si las pruebas eran legibles como especificaciones, las encontrarías útiles como introducción al código de otra persona (o recordando tu propio código). Es un gran poder de una buena suite de pruebas.

Leave a Reply

Your email address will not be published. Required fields are marked *