Unit Testing y el Patrón AAA
En la siguente entrada, voy a tratar de exponer de forma clara y concisa para el que no esté familizarizado en qué consiste el patrón AAA dentro de Unit Testing.
Dentro de los tests tenemos el fundamento, sintáxis o la regla de las tres A’s o el patrón AAA como también lo llaman algunas personas.
En mi caso me decanto por «patrón», pero en realidad lo he visto escrito de formas diferentes y lo importante de verdad es saber a qué nos estamos refiriendo.
Este patrón ha sido aceptado de forma global como forma habitual de escribir pruebas unitarias.
El patrón sugiere dividir una prueba unitaria (un método de pruebas) en tres secciones.
Cada una de las secciones tiene un cometido.
Las palabras en inglés a utilizar de estas tres secciones es lo que da nombre al patrón.
Por eso, el patrón AAA se organiza de la siguiente forma:
- Arrange (Organizar/Inicializa) => inicializa los objetos y establece los valores de los datos que vamos a utilizar en el Test que lo contiene.
- Act (Actuar) => realiza la llamada al método a probar con los parámetros preparados para tal fin.
- Assert (Confirmar/Comprobar) => comprueba que el método de pruebas ejecutado se comporta tal y como teníamos previsto que lo hiciera.
Como todos los patrones, no requiere que sean de obligado cumplimiento a la hora de escribir nuestros Tests.
Sin embargo, su uso es recomendable seguirlo como buena práctica siempre que sea posible, aunque hay veces en los que por naturaleza del Test, nos interesa más salir de la rigidez del patrón.
Pero hay algo que pasa desapercibido por lo general.
Hay varias razones indirectas de porqué usar el patrón AAA tiene beneficios indirectos.
El primer beneficio y más evidente que cualquier otro es que la organización de nuestros Tests hace que cualquier desarrollador pueda entenderlos rápidamente.
Éstos quedarán más claros y quedarán explicados por sí solos.
A la hora de escribir código de nuestro Test, hay quien indica en ellos mediante un comentario cada una de las partes (Arrange, Act, Assert).
Otros programadores prefieren hacer un salto de línea por cada parte.
Y otros añaden comentarios sólo para la parte Act y Assert, ya que el principio es lógicamente Arrange y no necesita comentario alguno.
Pero lo importante realmente es que los bloques de código que forman parte del patrón AAA dentro de un Test queden lo suficientemente claros.
Un aspecto muy a tener en cuenta del patrón AAA es que una vez realizada la parte de Arrange o inicialización, no deberíamos poder «tocar» los objetos inicializados.
Si hacemos esto por alguna razón, es posible que nuestro Test debiera estar refactorizado en más de un Test.
De hecho, una vez llevamos a cabo la inicialización del test, deberíamos centrarnos en ejecutar el proceso y verificar los resultados obtenidos.
Mucho código de inicialización es posiblemente un code smell sobre el que requiere prestar atención.
Por otro lado, si el método a probar dentro de nuestros Tests no se ajustan a la idea del patrón AAA por ser éstos más complejos, deberemos abrir por lo general un warning.
Ese warning nos ayudará a detectar posibles code smell en el código también.
Un beneficio más del patrón AAA es que eliminaremos duplicidades.
Esto dependerá de nosotros obviamente, pero será más fácil detectar Tests duplicados o innecesarios si ya se están realizando en otro Test.
Otro aspecto relativo en general a los Tests y no tanto a este patrón, es el uso de magic strings y magic numbers.
A la hora de escribir nuestros Tests, podremos detectar rápidamente que partes del código están abusando del uso de «datos mágicos».
Recuerda que cada Test es una función, y debe estar totalmente desacoplada.
Y ya saliéndonos un poco más del patrón, me gustaría mencionar que dentro del «mundo de los Asserts» podemos gestionar las comprobaciones de forma literal con el comando que el propio Framework de Unit Testing nos ofrezca para ello, o podemos basarnos en helpers o similares que nos faciliten sobre todo la comprensión lectora de lo que estamos validando o verificando en nuestro Test.
Para este propósito, podemos utilizar diferentes Frameworks de comprobación.
Uno de los más conocidos y que más se utiliza es Fluent Assertions.
Fluent Assertions no facilita la comprensión lectora sobre los Asserts.
De esta forma, nos permite leer nuestros Tests de forma más natural a como lo haríamos en el lenguaje humano.
Esto facilita que nuestros tests puedan ser comprendidos y leídos de forma más clara.
Un ejemplo de Test con xUnit y Fluent Assertions quedaría de la siguiente forma:
[Fact] public void Person_WithConstructorValues_ShouldBeNameAsExpected() { // Arrange var person = new Person("Jorge", 18); // Act var personName = person.GetName(); // Assert personName.Should().Equals("Jorge"); }
Como podemos observar en el ejemplo, he utilizado el Patrón AAA dentro del Test separando los bloques de código del Test, y en su Assert he utilizado Fluent Assertions para hacerlo todo más legible.
Y hasta aquí lo relativo a este patrón utilizado en Unit Testing.
Happy Coding!