¿Cómo puedo probar la unidad de una GUI?

154

Los cálculos en mi código están bien probados, pero debido a que hay mucho código GUI, la cobertura general de mi código es menor de lo que me gustaría. ¿Hay alguna guía sobre el código GUI de prueba de unidad? ¿Tiene sentido?

Por ejemplo, hay gráficos en mi aplicación. No he podido descubrir cómo automatizar la prueba de los gráficos. Se necesita un ojo humano, AFAIK, para verificar si el gráfico es correcto.

(Estoy usando Java Swing)

Steve McLeod
fuente
1
Hay un gran artículo sobre diferentes arquitecturas GUI de Martin Fowler ( martinfowler.com/eaaDev/uiArchs.html ). Describe las compensaciones de la arquitectura GUI en términos de pruebas unitarias.
Roman Hwang
1
Hoy en día, esta pregunta se haría mejor en programmers.stackexchange.com (y probablemente esté fuera de tema en Stack Overflow, por ser demasiado amplia), pero no se pueden migrar las preguntas antiguas. La cuestión de si pertenece aquí aparte, el problema sigue siendo interesante y difícil.
Mark Amery
1
Sería genial tener un ejemplo con algún código GUI y JUnit.
Witold Kaczurba
1
Yo diría que solo relájate y no te molestes. El esfuerzo realizado en las pruebas unitarias no siempre resulta ser productivo neto.
codeulike
Vieja pregunta aún, puedes probar el flujo en la GUI usando Jubula
Abi

Respuestas:

68

Los diseños como MVP y MVC generalmente intentan abstraer tanta lógica de la GUI real como sea posible. Un artículo muy popular sobre esto es "El cuadro de diálogo humilde" de Michael Feathers. Personalmente, he tenido experiencias mixtas al tratar de sacar la lógica de la interfaz de usuario: a veces ha funcionado muy bien y otras veces ha sido más problemático de lo que vale. Sin embargo, está algo fuera de mi área de especialización.

Jon Skeet
fuente
??? "a veces ha funcionado muy bien, y otras veces ha sido más problemático de lo que vale" Muy extraño porque la mayoría del lenguaje nuevo tiende a estar orientado a MVC ... lo cual es lógico en la interfaz gráfica de usuario (Model-Visual) ...
Patrick Desjardins
14
Aún así, la lógica de presentación estará en la GUI. A veces, eso puede estar lejos de ser trivial
Andrea
16
Mirror: The Humble Dialog Box
c24w
Tratamiento de Martin Fowler del concepto (en caso de que su red, como la mía, filtre archive.org): martinfowler.com/eaaDev/uiArchs.html#HumbleView
Christopher Berman
@ c24w gracias por tirar de ese espejo, eres el verdadero MVP :)
John Baker
38

Por supuesto, la respuesta es usar MVC y mover tanta lógica de la GUI como sea posible.

Dicho esto, hace mucho tiempo, un compañero de trabajo me dijo que cuando SGI estaba transfiriendo OpenGL a un nuevo hardware, tenían un montón de pruebas unitarias que dibujarían un conjunto de primitivas en la pantalla y luego calcularían una suma MD5 del búfer de trama. Este valor podría compararse con los valores de hash buenos conocidos para determinar rápidamente si la API es precisa por píxel.

dicroce
fuente
3
Me gusta este enfoque. Es complicado de configurar y mantener, pero me daría las capacidades de prueba de regresión que necesito.
Steve McLeod
77
danatel te perdiste el punto. OpenGL es una API de representación de gráficos con precisión de píxeles. Los marcos de aplicaciones GUI como Qt dependerán en gran medida del sistema Chrome, por lo que el hash del buffer de cuadros no es un buen enfoque.
Bob Somers
1
Un MD5? ¿Qué tiene que ver un hash criptográfico con esto? ¿Cómo se involucra la seguridad? Un hash, OK, ¿es una gran idea para gráficos perfectos en píxeles pero un hash criptográfico? Puede usar hashes más rápidos que no sean criptográficos y cuya probabilidad de colisión sea insignificante. ¿Estás seguro de que era un hash criptográfico y no simplemente un hash? (además de eso, en este día y época de la computación paralela, el algoritmo de hash [utilizado para fines no criptográficos] que no se puede paralelizar debe considerarse con sospecha)
SyntaxT3rr0r
24
@ SyntaxT3rr0r: ¿Qué función hash recomendaría en este tipo de aplicación no relacionada con la seguridad, y qué nivel de ganancia de rendimiento se podría esperar en comparación con MD5?
Lèse majesté
1
Su respuesta significa "nunca diseñe su GUI y, por lo tanto, no la pruebe". Frio.
Atenúa el
10

Puede probar UISpec4J es una biblioteca de prueba funcional y / o unitaria de código abierto para aplicaciones Java basadas en Swing ...

CMS
fuente
2
Empecé a usar UISpec4J durante un mes más o menos para hacer pruebas de validación de requisitos en la GUI de Java Swing. Me ha gustado mucho hasta ahora.
Bassam
github.com/UISpec4J/UISpec4J afirma que su enlace es el sitio web oficial, pero no me parece oficial. Todo lo que veo es un blog sobre vlogging
lucidbrot
7

Existe Selenium RC , que automatizará las pruebas de una interfaz de usuario basada en web. Grabará acciones y las reproducirá. Aún necesitará recorrer las interacciones con su interfaz de usuario, por lo que esto no ayudará con la cobertura, pero puede usarse para compilaciones automatizadas.

David Robbins
fuente
7

Puedes intentar usar Pepino y Swinger para escribir pruebas de aceptación funcional en inglés simple para aplicaciones Swing GUI. Swinger usa la biblioteca Jemmy de Netbeans debajo del capó para manejar la aplicación.

Pepino te permite escribir pruebas como esta:

 Scenario: Dialog manipulation
    Given the frame "SwingSet" is visible
    When I click the menu "File/About"
    Then I should see the dialog "About Swing!"
    When I click the button "OK"
    Then I should not see the dialog "About Swing!"

Echa un vistazo a este video demo de Swinger para verlo en acción.

Dema
fuente
6

Aquí hay algunos consejos:

Intente eliminar la mayor cantidad de código posible de la GUI (tenga controlador y objeto de modelo) de esta manera podrá probarlos sin la GUI.

Para el gráfico, debe probar el valor que proporciona al código que genera el gráfico.

Patrick Desjardins
fuente
6

La prueba es una forma de arte. Estoy de acuerdo en que la lógica debe eliminarse la GUI tanto como sea posible. Entonces podemos enfocar nuestra unidad de prueba allí. Como todo lo demás, las pruebas consisten en reducir el riesgo. No siempre necesita probar todo, pero muchas veces lo mejor es romper las diferentes pruebas en diferentes áreas.

La otra pregunta es qué estás tratando de probar realmente en la capa de la interfaz de usuario. La prueba de IU es la prueba más cara porque generalmente lleva más tiempo crearla, mantenerla y es la más frágil. Si prueba la lógica para saber que las coordenadas son correctas antes de intentar dibujar la línea, ¿qué está probando específicamente? Si desea probar se dibuja un gráfico con una línea roja. ¿Puede darle un conjunto de coordenadas predeterminadas y probar si ciertos píxeles son rojos o no rojos? Como se sugirió anteriormente, las comparaciones de mapas de bits funcionan, Selenium, pero mi enfoque principal no sería probar en exceso la GUI, sino probar la lógica que ayudará a crear la UI y luego enfocarme en qué parte de la UI se rompe o es sospechosa y enfocar un puñado de pruebas ahí.

Charles Smith
fuente
3

Puede usar JFCUnit para probar su GUI, pero los gráficos pueden ser más desafiantes. En un par de ocasiones tomé instantáneas de mi GUI y las comparé automáticamente con una versión anterior. Si bien esto no proporciona una prueba real, lo alerta si una compilación automática no produce el resultado esperado.

Steve Moyer
fuente
3

Lo que deduzco de su pregunta es que está buscando una forma automatizada de probar su comportamiento de GUI en detalle, el ejemplo que da es probar si una curva realmente se dibuja correctamente.

Los marcos de pruebas unitarias proporcionan una forma de hacer pruebas automatizadas, pero creo que el tipo de pruebas que desea hacer son pruebas de integración complicadas que verifican el comportamiento correcto de una multitud de clases, entre las cuales se encuentran las clases de su kit de herramientas / biblioteca GUI, que usted No debería querer probar.

Sus opciones dependen en gran medida de las plataformas / kits de herramientas / marcos que use: por ejemplo, una aplicación que usa Qt como marco de su GUI puede usar Squish para automatizar sus pruebas. Verifica los resultados de sus pruebas una vez, y las pruebas ejecutadas automáticamente posteriormente comparan los resultados con los resultados verificados.

andreas buykx
fuente
2

Mi enfoque para las pruebas de GUI está evolucionando, al igual que el consenso de la industria. Pero creo que algunas técnicas clave están comenzando a surgir.

Utilizo una o más de estas técnicas, dependiendo de la situación (por ejemplo, qué tipo de GUI es, qué tan rápido se necesita construir, quién será el usuario final, etc.).

  1. Prueba manual. Siempre tiene la GUI ejecutándose mientras trabaja en el código, y asegúrese de que esté sincronizada con el código. Usted prueba y vuelve a probar manualmente la parte en la que trabaja mientras trabaja en ella, cambiando entre el código y la aplicación en ejecución. Cada vez que completa un trabajo significativo, realiza una prueba general de toda la pantalla o área de la aplicación, para asegurarse de que no haya regresiones.

  2. Examen de la unidad. Escribe pruebas para funciones o pequeñas unidades de comportamiento de GUI. Por ejemplo, sus gráficos pueden necesitar calcular diferentes tonos de un color en función de un color 'base'. Puede extraer este cálculo a una función y escribir una prueba unitaria para ella. Puede buscar una lógica como esta en la GUI (especialmente la lógica reutilizable) y extraerla en funciones discretas, que pueden probarse más fácilmente en la unidad. Incluso el comportamiento complejo se puede extraer y probar de esta manera; por ejemplo, una secuencia de pasos en un asistente se puede extraer a una función y una prueba de unidad puede verificar que, dada una entrada, se devuelve el paso correcto.

  3. Explorador de componentes. Crea una pantalla de 'explorador' cuyo único rol es mostrar cada uno de los componentes reutilizables que componen su GUI. Esta pantalla le brinda una forma rápida y fácil de verificar visualmente que cada componente tiene la apariencia correcta. El explorador de componentes es más eficiente que pasar manualmente por toda la aplicación, porque A) solo tiene que verificar cada componente una vez, y B) no tiene que navegar profundamente en la aplicación para ver el componente, solo puede ver y verifíquelo de inmediato.

  4. Pruebas de automatización. Escribe una prueba que interactúa con la pantalla o el componente, simulando clics del mouse, entrada de datos, etc., afirmando que la aplicación funciona correctamente dadas estas manipulaciones. Esto puede ser útil como una prueba de respaldo adicional, para capturar posibles errores que sus otras pruebas podrían perder. Tiendo a reservar pruebas de automatización para las partes de la GUI que son más propensas a romperse y / o son muy críticas. Partes donde quiero saber lo antes posible si algo se ha roto. Esto podría incluir componentes interactivos altamente complejos que son vulnerables a roturas o pantallas principales importantes.

  5. Prueba de diferencia / instantánea. Escribe una prueba que simplemente captura el resultado como una captura de pantalla o como código HTML y lo compara con el resultado anterior. De esa manera, te alertan cada vez que cambia la salida. Las pruebas de diferencias pueden ser útiles si el aspecto visual de su GUI es complejo y / o está sujeto a cambios, en cuyo caso, desea una retroalimentación rápida y visual sobre el impacto que un cambio dado tiene en la GUI en su conjunto.

En lugar de utilizar cualquier tipo de prueba de manera forzada, prefiero elegir la técnica de prueba según el tipo de cosas en las que estoy trabajando. Entonces, en un caso extraeré una función simple y la probaré unitariamente, pero en otro caso agregaré un componente al explorador de componentes, etc. Depende de la situación.

No he encontrado que la cobertura de código sea una métrica muy útil, pero otros pueden haberle encontrado utilidad.

Creo que la primera medida es el número y la gravedad de los errores. Su primera prioridad es probablemente tener una aplicación que funcione correctamente. Si la aplicación funciona correctamente, debería haber pocos o ningún error. Si hay muchos errores graves o graves, entonces, presumiblemente, no está realizando la prueba o sus pruebas no son efectivas.

Además de reducir errores, existen otras medidas como el rendimiento, la usabilidad, la accesibilidad, la capacidad de mantenimiento, la extensibilidad, etc. Éstas diferirán según el tipo de aplicación que esté creando, el negocio, el usuario final, etc.

Todo esto se basa en mi experiencia personal e investigación, así como en una excelente reseña sobre las pruebas de IU de Ham Vocke .

Jonathan
fuente
1

Por lo que sé, esto es bastante complicado y realmente depende del idioma: numerosos idiomas tienen su propia forma de probar la GUI, pero si realmente necesita probar la GUI (a diferencia de la interacción modelo / GUI), a menudo tiene que simular un usuario real haciendo clic en los botones. Por ejemplo, el marco SWT utilizado en Eclipse proporciona SWTBot , JFCUnit ya se ha mencionado, Mozilla tiene su propia forma de simular esto en XUL (y de lo que he leído en sus blogs, estas pruebas parecen ser bastante frágiles).

A veces tiene que tomar una captura de pantalla y probar la representación perfecta de píxeles (creo que Mozilla hace esto para verificar las páginas correctamente representadas); esto requiere una configuración más larga, pero podría ser lo que necesita para los gráficos. De esa manera, cuando actualice su código y se rompa una prueba, deberá verificar manualmente la imagen si el fallo fue real, o mejoró el código de representación gráfica para generar gráficos más bonitos y necesita actualizar las capturas de pantalla.

Kim Sullivan
fuente
0

Si está utilizando Swing, FEST-Swing es útil para manejar su GUI y probar afirmaciones. Hace que sea bastante sencillo probar cosas como "si hago clic en el botón A, se debe mostrar el cuadro de diálogo B" o "si selecciono la opción 2 del menú desplegable, todas las casillas de verificación deberían estar deseleccionadas" .

El escenario gráfico que mencionas no es tan fácil de probar. Es bastante fácil obtener cobertura de código para los componentes de la GUI con solo crearlos y mostrarlos (y quizás conducirlos con FEST). Sin embargo, hacer afirmaciones significativas es la parte difícil (y la cobertura del código sin afirmaciones significativas es un ejercicio de autoengaño). ¿Cómo se prueba que el gráfico no se dibujó al revés o que no era demasiado pequeño?

Creo que solo tiene que aceptar que algunos aspectos de las interfaces gráficas de usuario no pueden probarse de manera efectiva mediante pruebas unitarias automatizadas y que tendrá que probarlas de otras maneras.

Dan Dyer
fuente
0

No es su trabajo probar la biblioteca GUI. Por lo tanto, puede eludir la responsabilidad de verificar lo que realmente se dibuja en la pantalla y verificar las propiedades de los widgets, confiando en la biblioteca que representan con precisión lo que se dibuja.

ivan_pozdeev
fuente