Intenté escribir pruebas unitarias de interfaz de usuario para mis aplicaciones GUI y me enfrento al problema de que, aunque funcionan bien cuando las escribo inicialmente, resultan quebradizas y se rompen cada vez que cambia el diseño (es decir, con bastante frecuencia). Estoy luchando por encontrar un conjunto de pautas que me lleven a tener pruebas unitarias mantenibles para la GUI.
Por ahora, una cosa que descubrí es que las pruebas que dicen "este componente debería mostrar sus datos de entrada en algún lugar" son buenas (y eso es muy fácil con HTML). Las pruebas que verifican un estado específico de una parte específica del componente suelen ser frágiles. Las pruebas que van como clic-clic-clic-esperar, que intentan seguir el comportamiento del usuario y la lógica empresarial subyacente (que es la parte más importante) generalmente resultan frágiles. ¿Cómo escribo buenas pruebas?
Para ser más precisos, me gustaría conocer algunos patrones sobre qué podría probar en mi interfaz de usuario, no exactamente cómo hacerlo. Las convenciones de nomenclatura y los identificadores fijos son buenos, pero no resuelven el problema central, es decir, que las GUI cambian mucho. Me gustaría probar los comportamientos que es poco probable que cambien. ¿Cómo encontrar lo correcto para probar?
Respuestas:
Un problema común con las pruebas de GUI ... La razón principal por la que estas pruebas se consideran frágiles es porque no pueden sobrevivir a un cambio en la GUI que no es un cambio en los requisitos . Debe esforzarse por estructurar su código de prueba de tal manera que un cambio en la GUI esté aislado en un solo lugar en las pruebas.
Como ejemplo, considere una prueba redactada como:
Mucho espacio aquí para que esta prueba se rompa cuando reelaboras la interfaz, incluso si el requisito para la validación permanece.
Ahora, pongamos esto en una pequeña redacción alternativa:
La prueba es la misma, los requisitos son los mismos, pero este tipo de prueba sobrevivirá a un cambio de imagen para su interfaz de usuario. Necesitará cambiar el código, obviamente, pero el código estará aislado. Incluso si tiene diez o veinte pruebas de este tipo para su página de perfil y mueve su lógica de validación de mensaje de error de alertas de JavaScript a jquery-popups, por ejemplo, solo necesita cambiar la parte de prueba única que verifica los mensajes de error.
fuente
Este es un problema común. Me gustaría prestar atención a:
Cómo nombras elementos
Use css id o class para identificar elementos. Favorezca el uso de la ID de CSS cuando el objeto es único. Considere el marco que está utilizando, por ejemplo, con Ruby on Rails, el
name
atributo se asigna automáticamente y puede (no intuitivamente) ser mejor que usar el id o la clase cssCómo identificas los elementos.
Evite identificadores posicionales como
table/tr/td/td
a favor de formas comotd[id="main_vehicle"
otd[class='alternates']
. Considere usar atributos de datos cuando sea apropiado. Incluso mejor trate de evitar etiquetas de diseño como<td>
por ejemplo, para lo anterior, puede agregar un intervalo y usarlo, por ejemplo,<span id="main_vehicle">
o un selector de comodín, como*[id="main_vehicle"]
donde*
ahora podría ser un div, span, td, etc.Usar atributos de datos específicos de prueba que solo se usan para qa y pruebas.
Evite la calificación innecesaria para los elementos. Puede encontrarse usando lo siguiente:
body.main div#vehicles > form#vehicle input#primary_vehicle_name
Sin embargo, esto requiere que el campo de entrada permanezca en un formulario con una identificación exacta del vehículo y en una página con un cuerpo que tenga una clase de main y un div con una identificación de vehículos que tenga un elemento secundario inmediato de un formulario con una identificación de vehículo. Cualquier cambio en cualquiera de esa estructura y la prueba se rompe. En este caso, puede encontrar que
input#primary_vehicle_name
es suficiente para identificar de forma única el elemento.
Evite las pruebas que hacen referencia a texto visible. El texto en la página que se muestra al usuario generalmente cambia con el tiempo a medida que el sitio se mantiene y actualiza, así que use identificadores como css id y css class o atributos de datos. Elementos como
form
,input
yselect
utilizados en formularios también son buenas partes de elementos de identificación, generalmente en combinación con id o clase, por ejemplo,li.vehicle
oinput#first-vehicle
También puede agregar sus propios identificadores, por ejemplo<div data-vehicle='dodge'>
. De esta forma, puede evitar el uso de las ID o clases de elementos, que los desarrolladores y diseñadores pueden cambiar. De hecho, con el tiempo descubrí que es mejor trabajar con desarrolladores y diseñadores y llegar a un acuerdo sobre los nombres y los ámbitos. Es difícil.Cómo se mantienen los datos fijos.
Similar a la identificación de elementos reales, trate de evitar valores de identificación del selector codificado en línea a favor de los objetos de la página: pequeños fragmentos de texto que se mantienen en variables o métodos y, por lo tanto, pueden reutilizarse y también mantenerse centralmente. Ejemplos de variables de JavaScript que siguen este patrón para valores codificados:
Más sobre objetos de página en selenium wiki y selenium docs
Comunicación con desarrolladores.
Independientemente del enfoque técnico en términos de "los desarrolladores realizan cambios y rompen la automatización del control de calidad", es un problema de flujo de trabajo. Debe asegurarse de que: todos son uno mismo equipo; el desarrollador ejecuta las mismas pruebas integradas; los estándares son acordados y seguidos por ambos grupos; la definición de hecho incluye ejecutar y posiblemente actualizar las pruebas de IU; los desarrolladores y el probador se emparejan en los planes de prueba y ambos asisten a la preparación del boleto (si está haciendo Agile) y hablan sobre las pruebas de IU como parte de la preparación. Debe asegurarse de que cualquier enfoque y estrategia que utilice para nombrar esté coordinado con los desarrolladores de aplicaciones. Si no llega a la misma página, le gustará el choque sobre la denominación de objetos. Algunos ejemplos de métodos de objetos de página que creé recientemente para un proyecto ruby:
Aquí están los mismos objetos de página que las variables de JavaScript:
fuente
La razón por la cual las personas desarrollaron cosas como MVC, MVP y presentador primero, y patrones de diseño similares, fue para separar la lógica empresarial de la interfaz de usuario.
Obviamente, la parte de vista solo se puede probar iniciando el programa y verificando lo que muestra; en otras palabras, solo se puede probar en las pruebas de aceptación.
Por otro lado, la prueba de la lógica empresarial se puede hacer en pruebas unitarias. Y esa es la respuesta a tu pregunta. Pruebe todo en el modelo, y si puede y quiere, también puede probar el código del controlador.
Eso solo puede suceder cuando tienes requisitos cambiantes. Cuando un requisito cambia, no hay forma de evitarlo, excepto modificar el código. Si logra crear un buen diseño y arquitectura, el cambio no se propagará en muchos lugares.
fuente
Las pruebas de interacción GUI no deben ser más o menos frágiles que cualquier otro tipo de pruebas. Es decir; Si su aplicación está cambiando de alguna manera, las pruebas deben actualizarse para reflejarlo.
Como una comparación:
Prueba de unidad
Original :
validateEmail()
debe lanzar unInvalidData
excepción. Que está cubierto correctamente en su prueba de unidad.Cambio :
validateEmail()
debería lanzar unaInvalidEmail
excepción. Ahora su prueba es incorrecta, la actualiza y todo vuelve a estar verde.Prueba de GUI
Original : al ingresar un correo electrónico no válido, aparecerá un cuadro de error emergente que contiene "Datos ingresados no válidos". Detectado correctamente por sus pruebas.
Cambio : ingresar un correo electrónico no válido dará como resultado un error en línea que contiene "Correo electrónico no válido ingresado". Ahora su prueba es incorrecta, la actualiza y todo vuelve a estar verde.
Recuerde que está probando entradas y salidas, un comportamiento bien definido. Independientemente de si es una prueba de GUI o una prueba de Unidad o una prueba de Integración, etc.
fuente