User:Iho jose/units/general

Por Jose Buelvas:

Reglas generales de pruebas unitarias, aplican a todos los lenguajes de programación. Pero cada lenguaje de programación aplica un método para hacerlas según el framework desarrollado para ello.

¿Qué es una prueba unitaria?
Una prueba unitaria es una unidad de código para asegurarse de que se realiza la tarea que se supone debe hacerse. Se prueba el código en el nivel más bajo posible, se hace pruebas de cada método de una clase.

¿Qué es una unidad?
Cualquier módulo discreto de código que se pueda probar de forma aislada. La mayoría de clases y sus métodos. A esta clase por lo general se le refiere como "clase bajo prueba" (Class Under Test, CUT por sus siglas en inglés) o el sistema bajo prueba (System Under Test, SUT por sus siglas en inglés).

Diferencia entre las pruebas unitarias y las pruebas de integración
Una prueba unitaria es el acto de probar una sola clase de forma aislada, completamente independiente de cualquiera de sus dependencias. Una prueba de integración es el acto de probar una sola clase junto con una o todas sus dependencias reales.

La instalación y desmontaje (SetUp y TearDown)
Cuando se realiza el método SetUp se ejecuta antes de cada prueba unitaria y el TearDown después de cada prueba unitaria.

En general se agregan todos los pasos previos a la prueba en el método SetUp y los métodos de limpieza en el TearDown. Pero solo se hacen estos métodos si son realmente necesarios para realizar las pruebas. Si no es así, estos pasos se toman dentro de cada prueba específica en la sección "arreglar".

Cómo lidiar con las dependencias
Muchas veces las clases usan dependencias de otras clases para ejecutar sus métodos. Para no depender de estas otras clases, hay que fingir estas. Se pueden crear estas clases a mano o usar un marco de aislamiento o maqueta. Un marco de aislamiento es una colección de código que permite la creación fácil de clases falsas.

Clases falsas
Cualquier clase que proporcione funcionalidad suficiente para pretender que es una dependencia necesaria para una CUT. Hay dos tipos de falsificaciones: Stubs y Mocks.
 * Stub: Una clase falsa que no tiene efecto en el paso o el fallo de la prueba y que existe puramente para permitir que la prueba se ejecute.
 * Mock: Una clase falsa que realiza un seguimiento del comportamiento de la CUT y pasa o falla la prueba basada en ese comportamiento.

1. Las pruebas unitarias encuentran errores.
Cuando se escribe un conjunto completo de pruebas que definen cuál es el comportamiento esperado para una clase determinada, se revela todo aquello que no se comporta como se espera.

2. Las pruebas unitarias mantendrán los errores alejados.
Haz un cambio que introduce un error y tus pruebas pueden revelarlo la próxima vez que ejecutes tus pruebas.

3. Las pruebas unitarias ahorran tiempo.
''Las pruebas unitarias ayudan a garantizar que su código funciona correctamente desde el principio. Las pruebas unitarias definen lo que su código debe hacer y por lo tanto no pasará tiempo escribiendo código que hace cosas que no debería hacer. Nadie comprueba en el código que no creen que funciona y usted tiene que hacer algo para hacerse pensar que funciona. Pasar ese tiempo para escribir pruebas unitarias.''

4. Las pruebas unitarias brindan tranquilidad.
''Puede ejecutar todas esas pruebas y saber que su código funciona como se supone. Saber el estado de su código, que funciona, y que puede actualizar y mejorar sin miedo es algo muy positivo.''

5. La prueba unitaria documenta el uso adecuado de una clase.
Las pruebas unitarias se convierten en ejemplos sencillos de cómo funciona su código, qué se espera que haga y la forma correcta de usar el código que está siendo probado.

1. Para la estructura de una prueba unitaria, siga la regla OAA (AAA en ingles - Arrange, Act, Assert).
Organizar: Configurar el objeto para ser probado. Al igual que las variables, campos y propiedades que permiten ejecutar la prueba, así como el resultado esperado.

Actuar: Llamar al método que está probando

Afirmar: Llame al marco de pruebas para verificar que el resultado de su "ejecución" es lo que se esperaba.

2. Prueba un objeto en el momento de aislamiento.
Todas las clases deben ser examinadas de forma aislada. No deben depender de nada más que los mocks y stubs. No deben depender de los resultados de otras pruebas.

3. Defina primero las pruebas simples.
Las primeras pruebas que usted defina deben ser las pruebas más simples. Deben ser las que sean básicas y fáciles de ilustrar la funcionalidad que está tratando de describir. Luego, una vez que pasen esas pruebas, debe comenzar a escribir las pruebas más complicadas que prueban los bordes y los límites de su código.

4. Denifir pruebas que prueben los límites.
Una vez que los fundamentos se prueban y usted sepa que su funcionalidad básica trabaja, debe probar los límites. Un buen conjunto de pruebas explorará los límites exteriores de lo que podría suceder a un método dado.

Por ejemplo:
 * ¿Qué ocurre si ocurre si sobrepasa el límite?
 * ¿Qué pasa si los valores pasan a cero o menos?
 * ¿Qué pasa si llega al entero mínimo o al entero máximo?
 * ¿Qué pasa si se crea un arco de 360 grados?
 * ¿Qué pasa si se pasa una cadena vacía?
 * ¿Qué pasa si la cadena tiene un tamaño 2GB?

5. Prueba a través de los límites.
Las pruebas unitarias deben probar ambos lados de un límite dado. Probar a través de los límites son lugares donde su código puede fallar o funcionar de maneras impredecibles.

6. Si puede, pruebe todo el espectro.
Si es práctico, pruebe todo el conjunto de posibilidades de su funcionalidad. Si se trata de un tipo enumerado, pruebe la funcionalidad con cada uno de los elementos de la enumeración. Podría ser poco práctico probar todas las posibilidades, pero si puedes probar todas las posibilidades, hazlo.

7. Si es posible, cubra cada ruta de código.
Éste también es desafiante, pero si su código está diseñado para realizar pruebas y utiliza una herramienta de cobertura de código, puede asegurarse de que cada línea de su código esté cubierta por pruebas unitarias al menos una vez. Cubrir cada ruta de código no garantiza que no haya errores, pero seguramente le da información valiosa sobre el estado de cada línea de código.

8. Definir pruebas que revelen un error para corregirlo.
Si encuentra un error, defina una prueba que lo revele. A continuación, podrá solucionar fácilmente el error depurando la prueba. Entonces usted tiene una prueba de regresión agradable para asegurarse de que si el error vuelve por cualquier razón, lo sabrá de inmediato. Es muy fácil arreglar un error cuando se tiene una prueba sencilla y directa para ejecutarse en el depurador.

Un beneficio lateral aquí es que has probado tu prueba. Debido a que has visto la prueba fallar y luego cuando lo has visto pasar, sabes que la prueba es válida en que se ha demostrado que funciona correctamente. Esto hace que sea una prueba de regresión aún mejor.

9. Haga que cada prueba sea independiente entre sí.
Las pruebas nunca deben depender el una de la otra. Si sus pruebas tienen que ejecutarse en un cierto orden, es necesario cambiar las pruebas.

10. Definir una afirmación por prueba.
Debe definir una afirmación por prueba. Si no puede hacerlo, refracte el código para que los eventos SetUp y TearDown se usen para crear correctamente el entorno de modo que cada prueba se pueda ejecutar individualmente.

11. Nombre sus pruebas con claridad así el nombre sea largo.
Puesto que usted está haciendo una afirmación por prueba, cada prueba puede llegar a ser muy específica. Por lo tanto, no tenga miedo de usar nombres de prueba largos y completos.

Un nombre completo y largo le permite saber inmediatamente qué prueba falló y exactamente qué estaba intentando hacer la prueba.

Las pruebas largas y claramente nombradas también pueden documentar sus pruebas. Una prueba llamada "DividedByZeroShouldThrowException" documenta exactamente lo que hace el código cuando intenta dividir por cero.

12. Prueba de que cada excepción planteada se plantea correctamente.
Si su código genera una excepción, escriba una prueba para asegurarse de que cada excepción que plantea se muestra cuando se supone que debe hacerlo.

13. Evite el uso de CheckTrue o Assert.IsTrue.
Evite comprobar si hay una condición booleana. Por ejemplo, si se va a comprobar que dos cosas son iguales con CheckTrue o Assert.IsTrue, utilice CheckEquals o Assert.IsEqual en su lugar. ¿Por qué? Debido a esto:

CheckTrue (Esperado, Actual) Esto informará algo como: "Alguna prueba falló: Se esperaba que era cierto, pero el resultado real era Falso".

Esto no te dice nada.

CheckEquals (esperado, real)

Esto le dirá algo como: "Alguna prueba falló: Se esperaba 7 pero el resultado real fue 3."

Sólo utilice CheckTrue o Assert.IsTrue cuando su valor esperado es realmente una condición booleana.

14. Ejecute las pruebas constantemente.
Ejecute sus pruebas mientras escribe código. Sus pruebas deben ejecutarse rápidamente, lo que le permite ejecutarlos incluso después de cambios menores. Si no puede ejecutar sus pruebas como parte de su proceso de desarrollo normal, entonces algo va mal. Se supone que las pruebas unitarias se ejecutan casi al instante. Si no lo son, probablemente es porque no los están ejecutando aisladamente.

15. Ejecute sus pruebas como parte de una compilación automatizada.
Así como usted debe estar ejecutando la prueba mientras se desarrolla, también deben ser una parte integral de su proceso de integración continua. Una prueba fallida debería significar que su compilación está rota. No deje que las pruebas fallantes se demoren. Considérelo como un error de compilación y solucionelo inmediatamente.

Manual de pruebas unitarias por lenguaje y framework

 * Pruebas unitarias en proyectos JavaScript/AngularJS con NodeJS.