¿Es este un olor a prueba o es aún peor?

7

Recientemente he estado viendo algunos guiones de prueba que se parecen un poco a

...
try {
  receiveSomething();
  // something was received even though it shouldn't
  failTest();
} catch (TimeoutException e) {
  // nothing should be received
  succedTest();
}

El problema que tengo con estos tipos de pruebas es

  1. No son deterministas. No sabe si no se envió nada a propósito o si todo se ha estrellado.
  2. Es muy difícil probar simultáneamente otra cosa, que en realidad podría, en este caso, enviar algo.

Mis pensamientos son, por un lado, ¿cómo se puede diseñar mejor este tipo de pruebas y, en segundo lugar, esto puede ser una indicación de un mayor olor del diseño del software que se está probando?

EDIT

Para aclarar, estos scripts de prueba se usan para pruebas de caja negra de software complejo basado en eventos, no para pruebas unitarias, y mi sensación es que el evento de "no hacer nada" es muy ambiguo. :)

    
pregunta Theodor 14.02.2013 - 11:07

4 respuestas

10

Por lo que escribiste, supongo que tu situación es más como esta

startAsynchronousComplexOperation();
try {
  receiveSomething(); // listen for events from that async operation above

  // something was received even though it shouldn't
  failTest();
} catch (TimeoutException e) {
  // nothing should be received
  succedTest();
}

y el objeto bajo prueba no es "recibir Algo", sino la operación asíncrona. Por lo tanto, el resultado de esa prueba depende de la velocidad de la máquina de prueba, si se ejecutan muchos otros procesos en la máquina de prueba, etc., y esto no es determinista.

En mi humilde opinión, esto es realmente un problema de diseño, y no solo un "olor a prueba". Si su "operación compleja" falla, o simplemente "lleva demasiado tiempo", no solo su prueba dará un "falso negativo". Piensa en cómo lidiar con esa situación en la producción. ¿No hay ningún requisito para determinar con seguridad que su "operación compleja" aún está viva y no se bloqueó? Así que puede pensar en agregar algún tipo de "perro guardián" o "mantener vivo el envío de paquetes" a su programa para obtener control sobre eso. Y una vez que tenga un mecánico disponible, puede usarlo en sus pruebas de esta manera:

startAsynchronousComplexOperation();
while(isComplexOperationStillAlive())
{
    try {
       receiveSomething(); // listen for events from that async operation above
       // something was received even though it shouldn't
       failTest();
   } catch (TimeoutException e) {
   }
}
if(didComplexOperationCrash())
    failTest();
else
    succedTest();
    
respondido por el Doc Brown 14.02.2013 - 14:18
12
  

No son deterministas. No sabe si no se envió nada a propósito o si todo se ha estrellado.

No importa, en el contexto de esta prueba. Lo único que importa es que, bajo las condiciones previas definidas, no se recibe nada. Otras pruebas pueden simular otras condiciones previas y verificar que sus resultados sean los esperados.

  

Es muy difícil probar simultáneamente otra cosa, que en realidad podría, en este caso, enviar algo.

¡Bien! No debe intentar conectar otras pruebas a esta prueba. Esta prueba está haciendo exactamente lo que debería estar haciendo. Un conjunto de condiciones previas = > Un resultado.

Esta es la definición misma del determinismo.

    
respondido por el pdr 14.02.2013 - 12:52
1

Muy difícil de responder sin un poco de contexto.

Si el caso de prueba fuera para el punto de función ("El sistema no responderá a ninguna solicitud después de que se haya emitido el comando 'Quiesce'"), entonces este sería un caso de prueba perfectamente válido.

Aunque hubiera especificado que se recibiera una respuesta válida inmediatamente antes de la solicitud de cierre, pero este tipo de pruebas "operativas" son muy difíciles de automatizar ya que es poco probable que pueda emitir dichos comandos de sistema desde una API.

    
respondido por el James Anderson 14.02.2013 - 11:24
1
  

No son deterministas. No sabe si no se envió nada a propósito o si todo se ha estrellado.

Un algoritmo determinista como se define en Wikipedia es como tal:

  

es un algoritmo que, dada una entrada particular, siempre producirá la misma salida

Pero los algoritmos para construir la prueba apenas importan, más o menos porque se supone que prueban el estado adecuado después de invocar un comportamiento específico. En otras palabras, lo único que debe ser determinista es el módulo de código que está probando. La prueba en sí está definiendo realmente cuál debería ser la determinación .

  

Es muy difícil probar simultáneamente otra cosa, que en realidad podría, en este caso, enviar algo.

Como han señalado otros, eso es algo BUENO. Si tengo una prueba para el módulo A, que tiene dependencias en los módulos B y C, entonces si falla TestModuleA, ¿cómo puedo saber que realmente es un problema en el módulo A?

Se supone que su prueba solo debe verificar que el Módulo A proporciona el estado correcto para invocar una operación de A. También debe tener pruebas separadas para las dependencias para verificar su comportamiento correcto.

    
respondido por el maple_shaft 14.02.2013 - 13:02

Lea otras preguntas en las etiquetas