Pregunta

He estado leyendo sobre TDD y me gustaría usarlo para mi próximo proyecto, pero no estoy seguro de cómo estructurar mis clases con este nuevo paradigma. El lenguaje que me gustaría usar es Java, aunque el problema no es realmente específico del idioma.

El proyecto

Tengo algunas piezas de hardware que vienen con una interfaz ASCII sobre RS232. Puedo emitir comandos simples y obtener respuestas simples, y controlarlas como si estuvieran en sus paneles frontales. Cada uno tiene una sintaxis ligeramente diferente y conjuntos de comandos muy diferentes. Mi objetivo es crear una abstracción / interfaz para poder controlarlos todos a través de una GUI y / o llamadas a procedimientos remotos.

El problema

Creo que el primer paso es crear una clase abstracta (no me gustan los nombres, ¿qué tal 'Communicator'?) para implementar todo el material como Serial I / O, y luego crear una subclase para cada dispositivo. Estoy seguro de que será un poco más complicado que eso, pero ese es el núcleo de la aplicación en mi mente.

Ahora, para las pruebas unitarias, no creo que realmente necesite el hardware real o una conexión en serie. Lo que me gustaría hacer es entregar a mis comunicadores un InputStream y un OutputStream (o Reader y Writer) que podrían ser desde un puerto serie, archivo, stdin / stdout, canalizado desde una función de prueba, lo que sea. Entonces, ¿me gustaría que el constructor de Communicator los tome como entradas? Si es así, sería fácil poner la responsabilidad de configurarlo todo en el marco de prueba, pero en realidad, ¿quién hace la conexión real? ¿Un constructor separado? ¿La función llamando de nuevo al constructor? Una clase aparte, ¿cuál es el trabajo de 'conectar' el comunicador a los flujos de E / S correctos?

Editar

Estaba a punto de volver a escribir la sección del problema para obtener respuestas a la pregunta que pensé que estaba haciendo, pero creo que lo resolví. He identificado (¿correctamente?) Dos áreas funcionales diferentes.

1) Tratar con el puerto serie

2) Comunicación con el dispositivo (entendiendo su salida y generando comandos)

Hace unos meses, lo habría combinado todo en una clase. Mi primera idea para romper con esto fue pasar solo los flujos de IO a la clase que entiende el dispositivo, y no pude averiguar quién sería el responsable de crear los flujos.

Habiendo investigado más sobre la inversión de control, creo que tengo una respuesta y . Tenga una interfaz y clase separadas que resuelvan el problema # 1 y pásenlas al constructor de las clases que resuelven el problema # 2. De esa manera, es fácil probar ambos por separado. # 1 conectándose al hardware real y permitiendo que el marco de prueba haga cosas diferentes. El # 2 se puede probar si se le da un simulacro del # 1.

¿Esto suena razonable? ¿Necesito compartir más información?

¿Fue útil?

Solución

Con TDD, debe dejar que su diseño emerja , comenzar poco a poco, con pasos de bebé y hacer crecer su examen de clase poco a poco.

CLARIFICADO: comienza con una clase concreta, para enviar un comando, prueba de unidad con un simulacro o un talón. Cuando funcione lo suficiente (quizás no con todas las opciones), pruébelo contra su dispositivo real, una vez, para validar su simulador / simulador.

Una vez que la clase para el primer comando esté operativa, comience a implementar un segundo comando, de la misma manera: primero nuevamente su simulacro / talón, luego una vez contra el dispositivo para validación. Ahora, si está viendo similitudes entre sus dos clases, puede refactorizar su diseño abstracto basado en clases, o algo diferente.

Otros consejos

Lo siento por estar un poco centrado en Linux ..

Mi forma favorita de simular gadgets es escribir controladores de dispositivo de caracteres que simular su comportamiento. Esto también le brinda capacidades divertidas, como proporcionar una interfaz ioctl () que hace que el dispositivo simulado se comporte de manera anormal.

En ese punto ... desde la prueba hasta el mundo real, solo importa qué dispositivo (s) realmente abre, lee y escribe.

No debería ser demasiado difícil imitar el comportamiento de sus gadgets ... parece que toman instrucciones muy básicas y devuelven respuestas muy básicas. Una vez más, un simple ioctl () podría decirle al dispositivo simulado que es hora de portarse mal, por lo que puede asegurarse de que su código maneje dichos eventos adecuadamente. Por ejemplo, falla intencionalmente en cada enésima instrucción, donde n se selecciona aleatoriamente en la llamada a ioctl ().

Después de ver tus ediciones, creo que vas en la dirección correcta. TDD tiende a llevarlo hacia un diseño compuesto de clases pequeñas con una responsabilidad bien definida. También me gustaría repetir el consejo de tinkertim: un simulador de dispositivo que puedes controlar y " provocar " El hecho de comportarse de diferentes maneras es invaluable para las pruebas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top