Header Ads Widget

Ticker

6/recent/ticker-posts

Una clase de prueba de Java no prueba una clase

 Si escribe las pruebas mal, termina con un accesorio de prueba cuajado , donde hay un lío impío de pruebas no relacionadas en la misma clase.

En la entrevista

Una gran pregunta para una entrevista de trabajo es preguntarle a alguien qué automatización de pruebas ha construido y cómo llegó a hacerlo.

Una respuesta no muy buena es "ninguna" . En mi experiencia, peor es la persona que responde “Tengo que escribir una clase de prueba para cada clase y un método de prueba para cada método” . Al fijarse en el código que se está probando, en lugar de los comportamientos y la naturaleza de la construcción de un escenario, a menudo se realiza precisamente el tipo de prueba incorrecto.

Pruebe el comportamiento desde diferentes perspectivas

El objetivo es establecer algún tipo de escenario y luego probar el comportamiento dentro de ese escenario. El mismo código bajo prueba puede comportarse de manera diferente dependiendo de con qué lo integremos. Es situacional.

Por lo tanto, no se sigue que una sola clase deba probarse de otra clase de prueba. Tampoco se sigue que una sola clase de prueba solo se centre en una parte del sistema.

A partir de la pirámide de pruebas, podríamos asumir que las pruebas de nivel más bajo tendrán accesorios que se centrarán solo en una pequeña parte del sistema. Sin embargo, otro accesorio puede mirar más lejos.

Los accesorios pasan a ser clases

Se vuelve confuso porque resulta que la convención es crear una clase de prueba para probar una clase. Entonces, la suposición natural es que mantengas todas las pruebas en esa clase. Es una buena suposición de trabajo, ya que a menudo es cierto.

Sin embargo, tenga cuidado con si la prueba comienza a realizar un conjunto diverso de pruebas diferentes. La forma más fácil de detectarlo es mirando las propiedades de la clase de prueba, configurada cada vez. ¿Cada caso de prueba utiliza la mayoría de los recursos disponibles?

Cómo decidir un accesorio de prueba

Instintivamente podemos comenzar creando la mecánica habitual de una clase de prueba. Algo como esto:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
class MyTest {
   // some test input or expected output
   private static final SomeObject COMPLEX_DATA = new ...;
 
   private Thing whatWeAreTesting = new ...;
 
   // ... other resources
 
   @BeforeEach
   void beforeEach() {
       // some additional setup
   }
 
   @AfterEach
   void afterEach() {
       // some tidy up
   }
 
   @Test
   void testOne() { ... }
}

Tiendo a comenzar una prueba con algo de lo anterior en su lugar, generalmente agregando beforeEachafterEachcaso por caso si es necesario.

Pero, ¿y si no pudiéramos utilizar ninguno de los valores de nivel de objeto? ¿Y si no pudiéramos crear recursos estáticos? ¿Qué incluiría cada uno de nuestros métodos de prueba?

Habría algunas cosas de configuración repetidas, habría algunas cosas que podrían repetirse, pero no es una configuración común, tanto como los ejemplos de prueba que pueden usarse en diferentes contextos de una prueba a la siguiente, y habría algunos cosas que son únicas o que se usan con poca frecuencia.

Si tuviera que imaginar la prueba refactorizada a métodos independientes, puede encontrar algunas situaciones:

  • Se está repitiendo alguna configuración global en múltiples pruebas, lo que implica que estas pruebas deberían vivir en un solo dispositivo con un patrón beforeAll/afterAll
  • Algunas configuraciones se repiten en todas las pruebas, lo que sugiere la configuración a nivel de objeto, quizás con beforeEachafterEachdependiendo de lo fácil que sea configurar las cosas
  • Algunas cosas se usan para un subconjunto de pruebas, lo que sugiere que se requieren múltiples accesorios

Las pruebas pueden compartir la implementación

Puede haber clases base para las pruebas, y la herencia de la implementación de la prueba no es, en mi opinión, un anti-patrón.

De manera similar, las pruebas pueden compartir una fábrica de datos de prueba para producir objetos complejos tanto para la entrada de prueba como para la salida esperada.

Resumen

Las pruebas necesitan un diseño de primera clase, así como el código que prueban. Un dispositivo de prueba es distinto de una clase de prueba, aunque uno requiere otro, por supuesto.

Publicar un comentario

0 Comentarios