2011-11-02 14 views
6

que estoy involucrado con un proyecto que debe, entre otras cosas, el control de varios instrumentos de laboratorio (robots, lectores, etc ...)código Prueba de la unidad con dependencias externas impredecibles

La mayoría de estos instrumentos son controlados ya sea a través Controladores basados ​​en DCOM, el puerto serie o iniciando programas propietarios con varios argumentos. Algunos de estos programas o controladores incluyen el modo de simulación, otros no. Obviamente, mi computadora de desarrollo no se puede conectar a todos los instrumentos, y aunque puedo encender máquinas virtuales para los instrumentos cuyos controladores incluyen un modo de simulación, algunas cosas no se pueden probar sin el instrumento real.

Ahora, mi propio código no es principalmente acerca de las operaciones reales de los instrumentos, sino de iniciar operaciones, asegurándose de que todo está bien, y la sincronización entre la gran cantidad de ellos. Está escrito en Java, utilizando varias bibliotecas para interactuar con los instrumentos y sus controladores.

Quiero escribir pruebas unitarias para los distintos módulos de control de instrumentos. Sin embargo, debido a que los instrumentos pueden fallar de muchas maneras (algunas de las cuales están documentadas, algunas de las cuales no), debido a que el código depende de estas salidas parcialmente aleatorias, estoy un poco perdido con respecto a cómo escribir pruebas unitarias para estas partes de mi código. He considerado las siguientes soluciones:

  • única prueba con instrumentos reales conectados, posiblemente el método más preciso, pero no es práctico en absoluto (placa de inserción en lector, marcha de prueba unidad, retire la placa, prueba de la unidad de gestión, etc ...), por no mencionar potencialmente peligrosa,
  • utilizar un objeto de burla para simular la parte que realmente se comunica con la cosa; mientras que éste es definitivamente más fácil de implementar (y ejecución), puede que no sea capaz de reproducir toda la gama de posibles fallos (como se mencionó anteriormente, una gran cantidad es indocumentado, que a veces puede causar malas sorpresas)

Mientras Actualmente estoy pensando en ir con este último, ¿me estoy perdiendo algo? ¿Hay una mejor manera de hacer esto?

Respuesta

6

Sus dos puntos son opciones válidas, pero cada uno representa dos tipos diferentes de prueba.

En un nivel muy alto, el uso de objetos simulados (según su segundo punto) es excelente para las pruebas unitarias, que simplemente están probando su código (que es el sistema sometido a prueba o SUT) y nada más extraño que eso. Cualquier otra dependencia es burlada. A continuación, puede escribir casos de prueba para arrojar tantas condiciones de error diferentes como se pueda imaginar (además de probar el "camino feliz", por supuesto). El hecho de que su dominio de condiciones de error no esté documentado es desafortunado, y es algo que debe trabajar para restringir lo mejor posible. Cada vez que se encuentra con una nueva condición de error con el dispositivo externo real, debe averiguar cómo reproducirlo a través del código y luego escribir otra prueba de unidad nueva para recrear esa condición a través de su marco simulado.

Además, las pruebas con los instrumentos reales conectados (según su primer punto de viñeta) son excelentes para las pruebas de integración, que son más pruebas de su código junto con las dependencias externas reales.

En general, las pruebas unitarias deben ser rápidas (idealmente, menos de 10 minutos para compilar el código y ejecutar todo el conjunto de pruebas unitarias). Esto significa que obtendrá retroalimentación rápidamente de las pruebas unitarias, He escrito porque cualquier prueba falla. Las pruebas de integración, por su propia naturaleza, pueden demorar más (si, por ejemplo, uno de tus dispositivos externos tarda 1 minuto en calcular un resultado o realizar una tarea, y tienes 15 conjuntos diferentes de entradas que estás probando, eso es 15 minutos correctos allí para un pequeño conjunto de pruebas.) Su servidor de CI (debe tener uno de los que compila automáticamente y ejecuta todas las pruebas) debe activarse automáticamente al comprometerse con su repositorio de control de origen. Debe compilar y ejecutar las pruebas unitarias como un solo paso. Después de que se haya hecho esa parte, debería proporcionarle comentarios (buenos o malos), y luego, si la unidad prueba todos los pasos, debería iniciarse automáticamente sus pruebas de integración. Esto supone que hay un dispositivo real conectado a su servidor CI, o un reemplazo adecuado (lo que eso signifique en su entorno particular)

Espero que ayude.

+0

Pruebas unitarias: ya tengo compilación automática y pruebas unitarias para la mayor parte del proyecto (una gran parte se trata de almacenar/convertir/transmitir de forma segura los datos de los instrumentos). Sin embargo, para probar el código de control de los instrumentos correctamente, es probable que tarden mucho más tiempo en ejecutarse, ya que algunas de las condiciones de error implican tiempos de espera (que, de acuerdo, pueden alcanzar un valor razonable durante la prueba). Pero para la parte de integración, es más difícil, y no se puede automatizar en algunos casos, ya que implica la manipulación física de los instrumentos (por ejemplo, agregar un plato) –

4

Si está utilizando burla entonces se puede sustituir diferentes simulacros para llevar a cabo de manera diferente. Es decir, sus pruebas serán consistentes. Eso es valioso ya que ejecutar pruebas contra un sistema de rendimiento aleatorio no le dará una sensación de seguridad. Cada ejecución puede/ejecutará una ruta de código diferente.

Dado que usted no sabe todos los escenarios de fallo de antelación, creo que hay dos (no exclusivos) escenarios:

  1. captura los detalles de esos fracasos a medida que los ven y codifican más pruebas en tus burlas para replicar estos. En consecuencia, su registro debe ser sólido para capturar los detalles de la falla. A medida que pasa el tiempo, su conjunto de pruebas se ampliará para abarcar y probar la regresión estos escenarios.
  2. Sus interfaces con estos sistemas pueden ser capaces de capturar todos los errores, pero presentarlos en un subconjunto finito de errores. p.ej. clasifique todos los errores en (por ejemplo) errores de conexión, tiempos de espera, etc. De esta forma, puede restringir sus escenarios a un pequeño conjunto de fallas. No sé si esto es práctico para su aplicación, desafortunadamente.
3

No puede probar la unidad algo que no ha previsto, por definición.

El segundo enfoque es apropiado para pruebas de unidad. Tener los instrumentos reales conectados lo convierte en en el mejor una prueba de integración.

Divida las dependencias para que pueda crear un instrumento falso y luego haga que simule la realidad de tantas formas como sea posible. A medida que su comprensión de la realidad mejore, actualice su falso y agregue pruebas para enfrentar esa situación. (Burlarse puede ser apropiado en algunos casos, falsificar en otros.)

Cuestiones relacionadas