Cómo estructurar pruebas unitarias para una aplicación GUI usando C # y NUnit

16

Me han pedido que haga un pequeño proyecto paralelo para suministrar una aplicación simple a uno de nuestros clientes. Normalmente estaría trabajando en el código de fondo donde tengo todas mis necesidades de prueba resueltas, y todavía no he tenido el dudoso placer de escribir pruebas para la GUI, por lo que no me queda claro cómo debo configurar el código de prueba y las herramientas para un EXE.

Mi primer instinto fue simplemente incluir las pruebas con el código de la aplicación, sin embargo, eso requeriría el suministro de una serie de dependencias específicas de la prueba, que me han indicado que no envíe específicamente al cliente. Tampoco puedo sacar dinero para una herramienta de prueba especialmente diseñada, así que necesito usar las herramientas que tengo a mano ( StoryQ , RhinoMocks y NUnit), que realmente debería ser más que suficiente para probar el comportamiento de una aplicación GUI simple. Así que, hasta donde puedo ver, esto me deja tratando de lograr un buen equilibrio entre mantener el diseño realmente simple o ingeniar excesivamente a propósito por el bien de las pruebas. Parece que estoy construyendo la aplicación con la lógica de negocios en una biblioteca separada y probando contra la biblioteca como lo haría normalmente, o buscando algún otro mecanismo que me permita acceder al ejecutable sin romper módulos adicionales que el diseño de la aplicación no realmente necesito.

Editar:
Tenga en cuenta que esta pregunta trata sobre cómo estructurar la relación entre NUnit y mi ejecutable, en lugar de una DLL, y no sobre cómo separar la presentación y la lógica empresarial.
/Editar

Entonces mi pregunta es:

  1. ¿Existe un método específico / recomendado para configurar una aplicación GUI simple con pruebas unitarias que me permita verificar adecuadamente el estado y el comportamiento, utilizando las herramientas que tengo a mano y sin recurrir a una ingeniería excesiva?
  2. ¿Me he perdido algo fundamental sobre la forma en que se debe invocar / configurar NUnit al probar un EXE (en lugar de una DLL)?
  3. ¿Me puede proporcionar o señalar en la dirección de ejemplos de cómo lograr todo esto?

Me doy cuenta de que puede haber más de una forma de hacer esto, así que estoy buscando pautas de implementación específicas basadas en su experiencia.

S.Robins
fuente
NUnit no está diseñado para probar GUI directamente. Debe separar su capa de presentación (es decir, la vista) de sus datos y la lógica empresarial (es decir, el modelo) para poder probar lo que entra en su vista sin usar la vista.
Bernard
1
@Bernard Esta pregunta no se trata de superponer una GUI para probar. Naturalmente, aplico todas mis aplicaciones, incluso las triviales, por lo que realmente no es un problema para mí. He editado la pregunta para adaptarla, y espero que aclare cualquier idea falsa. :)
S.Robins
1
No hay nada terriblemente complicado en las pruebas de unidades en EXE. Simplemente haga que su DLL de prueba haga referencia a su archivo EXE, y ya está listo.
whatsisname

Respuestas:

3

Mencioné en uno de mis comentarios a la respuesta de Simoraman que había pensado en un par de formas de hacer esto. Una de mis opciones era similar a la sugerencia en la respuesta de Jalayn de crear un proyecto duplicado y generar una DLL, mientras que mi otra idea era simplemente vincular a los archivos en el proyecto donde había código que quería probar. Si bien ambas opciones podrían funcionar, son menos que ideales.

En el segundo caso, tendría un desorden de dependencias de unidades para administrar a menos que realmente pudiera separar la arquitectura para minimizar las dependencias. Esto está bien para proyectos más pequeños, pero los más grandes podrían convertirse fácilmente en un verdadero desastre para administrar. Sin embargo, mi mayor resistencia a esta opción es la pura inelegancia de la misma. Claro que pudehacer que funcione, pero al hacerlo, efectivamente necesito romper la encapsulación para probar los componentes internos de un ensamblaje directamente a través de la fuente, en lugar de probar a través de las interfaces públicas, lo que en mi opinión es un gran no-no. Del mismo modo, tener un archivo de proyecto adicional significaría duplicar los esfuerzos en dos proyectos a la vez, o encontrar una manera de agregar la configuración del archivo del proyecto automáticamente a dos archivos a la vez, o recordar copiar y cambiar el nombre del campo del proyecto cada vez que construyo. Quizás esto se pueda automatizar en el servidor de compilación, pero sería difícil de administrar en el IDE. Una vez más, puede funcionar, pero es un error en el mejor de los casos, y una molestia en el peor si se equivoca.

Parece que la mejor manera es hacer lo que whatsisname comentó a mi pregunta, y simplemente incluir el EXE como referencia en el proyecto de prueba. Resulta que un EXE se trata efectivamente de la misma manera que una DLL en este caso, y puedo acceder a todas mis clases en capas para probar lo que flota en mi barco.

S.Robins
fuente
2

Creo que:

  • Su código de prueba comercial debe estar en un proyecto separado, probando su biblioteca de códigos comerciales.
  • Su código de prueba GUI debe estar en un proyecto separado, probando su biblioteca GUI. Ahora, cómo construir una biblioteca GUI en lugar de un ejecutable, intento responder más tarde.
  • Si tiene my.namespace.biz.MyClass, su clase de prueba debe ser my.namespace.biz.MyClassTest (o MyClassTestCase).
  • Si desea probar el código que se encuentra en su objetivo ejecutable, entonces debe tener una configuración que compila un EXE y otra configuración que construye una biblioteca (DLL) contra la cual iniciará sus pruebas.

Estas son las reglas que me gusta seguir, ya sea Java o C # (excepto que no hay ningún problema EXE con Java, por supuesto :-))

En cuanto a cómo configurar su entorno de prueba, me parece que tiene al menos estas dos opciones:

Usando MSBuild

Cree un clon de su archivo .proj (por ejemplo, myproject-as-dll.proj ). Cambie el OutputTypearchivo clonado de " EXE" a " Library". Con el comando MSBuild ahora puede crear una biblioteca que puede establecer como referencia en su proyecto que contiene casos de prueba de NUnit.

Me parece posible, pero nunca lo he usado con tanta honestidad, así que no estoy seguro. Además, es posible que no tenga MSBuild en su servidor de prueba de integración, y no sé si se puede separar de Visual Studio ...

Usando NAnt

Si no está familiarizado con NAnt, tendrá que buscar en Google cómo configurar sus proyectos con él. Tal vez echa un vistazo a esto , es un poco viejo, pero el autor ha comentado los archivos y NAnt Si encuentra que explica por sí mismo (. Editar: examinar su expediente más en detalle, encuentro su archivo de configuración extremadamente reutilizable ). También hace mucho más que simplemente construir, ya que ejecuta casos de prueba y lanza herramientas de cobertura de código. Ahora, admito que nunca he usado NAnt, a diferencia de su homólogo de Java y su padre "Ant", que he usado mucho, pero veo que es lo mismo y no creo que sea tan difícil de aprender.

Con esa herramienta, puede llegar a una configuración que le permitirá:

  • construya todos sus proyectos (lógica de negocios, GUI, etc.) en bibliotecas separadas
  • construye tus proyectos de prueba
  • inicie las pruebas (esa parte específica se realiza con la tarea NUnit2 ).
  • examine la cobertura de su código con la tarea NCover .

Con un poco más de código, incluso podrías:

  • realizar implementaciones nocturnas en su servidor de integración
  • Si NAnt está disponible en su servidor de integración, inicie pruebas de integración nocturnas con la ayuda de tareas programadas

Todo se hace sin cambiar nada en sus archivos de Visual Studio. Y, realmente, no me parece una ingeniería excesiva, es solo un archivo. Puede llevarle uno, tal vez dos días para que todo funcione, pero en mi opinión tendrá una buena configuración.

Por último, le daría al cliente todo lo necesario para construir, probar y ejecutar los proyectos. Tiendo a pensar que muestra tu profesionalismo y el hecho de que escribes código con calidad en mente (lo cual me parece que lo haces ya que estás buscando soluciones elegantes)

Jalayn
fuente
0

El hecho de que el proyecto sea pequeño (inicialmente) no significa que la arquitectura adecuada sea una ingeniería excesiva. El hecho de que desee escribir pruebas indica que su proyecto no es un truco único completamente trivial.

No mencionaste qué GUI-Framework estás utilizando. WPF MVVM (Model-View-ViewModel) es bueno y le permite escribir pruebas para toda la lógica con bastante facilidad. Con WinForms he escuchado cosas buenas sobre MVP (Model-View-Presenter)

simoraman
fuente
Escribo pruebas para todo el código que escribo. Incluso las cosas que podrías encontrar triviales. La única vez que no escribo un examen es cuando hago un pico. En este caso, estoy enviando una utilidad única a un cliente, por lo que las pruebas son más que un lujo, es un requisito para satisfacer nuestros estándares de calidad. En términos de "sobre ingeniería", esta no es una elección entre una arquitectura buena o mala, sino que evita la necesidad de imponer capas adicionales que no se requieren en este caso, ya que la aplicación tiene un solo propósito con un ciclo de vida relativamente corto.
S.Robins
En lo que respecta a la elección de gui-framework, no veo cómo esto afectará la forma en que se configura el entorno de prueba. Estoy buscando CÓMO implementar específicamente pruebas unitarias para la capa GUI utilizando las herramientas que tengo disponibles. Esta respuesta en particular no me dice nada al respecto.
S.Robins
Simoraman: si eliminaras el primer párrafo más bien crítico, esto sería obtener una respuesta. Arregla eso y eliminaré mi -1. @ S.Robins observa que el segundo párrafo es relevante, aunque no es una respuesta completa, sería útil. Si su capa de GUI es delgada, bien estructurada y obvia, y toda la lógica empresarial se prueba mediante pruebas unitarias en el nivel de Modelo, entonces es posible que no necesite la molestia adicional de probar la IU explícitamente.
Mark Booth
1
@MarkBooth Layering no es realmente un problema. Como simiraman menciona, puedo MVP, MVVM, o puedo construir algo aún más delgado. Sin embargo, tengo algunos elementos específicos de la GUI que requerirán pruebas explícitas, por lo que decidí escribir esto como una pregunta. Tengo un par de ideas, y si las cosas empeoran, sé que eventualmente podré resolver el problema y escribir una respuesta yo mismo. Sin embargo, quería abrir esto a la comunidad, ya que pensé que sería una buena pregunta para ProgrammersSE. ;-)
S.Robins
0

Eche un vistazo a mi respuesta a esta pregunta: ¿Cómo configuro MVP para una solución Winforms?

De hecho, he escrito una aplicación de muestra que muestra cómo superpongo y cómo pruebo mi GUI.

leyendo su edición: use un corredor de prueba que se integre con su entorno de desarrollo. Yo uso ReSharper.

Bryan Boettcher
fuente
Gracias por la recomendación de ReSharper. Esta es una herramienta que uso cuando desarrollo. Desafortunadamente, no ayudará cuando ejecute las pruebas en el servidor de compilación de integración. Tampoco me dice cómo configurar las pruebas de Nunit para acceder al código en un exe durante las pruebas.
S.Robins
1
Informalmente, lo hace. El exe es solo la vista, que carga el presentador, los modelos y los modelos de vista de una biblioteca de clases como parte del inicio de la aplicación. Al menos en mi solución, la vista es lo suficientemente tonta como para no probarla con pruebas automatizadas, y solo hacer pruebas de aceptación para asegurarnos de que las cosas estén bien escritas y los botones estén donde deberían estar. NUnit-testing un dll es muy fácil de hacer.
Bryan Boettcher
0

Había escrito Nunit WinForms hace unos años (6 años, supongo). Una cosa que recuerdo específicamente es que, aunque es un caso de prueba unitaria, también actúa como un caso de prueba de extremo a extremo. A veces no hay mucho que probar en un front-end (una forma simple). Entonces, aunque esté tratando de probar un cuadro de mensaje que aparece al hacer clic en un botón, está probando involuntariamente otros métodos de otras capas. Hay algunas cosas que no puede automatizar también. El aspecto, la sensación y la usabilidad no se pueden automatizar mediante pruebas unitarias automatizadas. Tendrá que ejecutar algunas pruebas manuales antes de lanzar.

ViSu
fuente
Si su cliente especifica que una pantalla debería verse de cierta manera, o debería cambiar de cierta manera, entonces debería ser capaz de probar estas cosas. La captura de especificaciones como pruebas es el corazón de la metodología BDD, y nunca he encontrado una situación en la que no pueda, aunque sea de forma creativa, encontrar un medio para automatizar una prueba. La verdadera pregunta es si las pruebas serán valiosas, si la aplicación se factoriza lo suficientemente bien como para permitirle automatizar todas las pruebas en primer lugar, y si las pruebas serán rentables. Sin embargo, estoy de acuerdo en que a veces no lo son.
S.Robins