El arte de las pruebas de diseño con Galen Framework
Publicado: 2022-03-10Al diseñar una interfaz gráfica de usuario, siempre hay una pregunta abierta: ¿Cómo automatizamos las pruebas? ¿Y cómo nos aseguramos de que el diseño del sitio web se mantenga receptivo y se muestre correctamente en todo tipo de dispositivos con varias resoluciones? Agregue a esto las complicaciones derivadas del contenido dinámico, los requisitos de internacionalización y localización, y se convierte en un verdadero desafío.
En este artículo, lo guiaré a través de una nueva e interesante técnica de prueba de diseño. Usando Galen Framework, proporcionaré un tutorial detallado para escribir pruebas de diseño generalizadas significativas, que se pueden ejecutar en cualquier navegador y en cualquier dispositivo y, al mismo tiempo, usarse como una única fuente de verdad en su documentación de diseño.
Lectura adicional en SmashingMag:
- Desarrollo basado en pruebas visuales para un diseño de interfaz receptivo
- Los fundamentos de la automatización de pruebas para aplicaciones, juegos y la web móvil
- Diversos marcos de automatización de pruebas para aplicaciones nativas de React
También demostraré cómo se me ocurrió una prueba optimizada para una página de mensajería en nuestro sitio web de anuncios clasificados, Marktplaats. Aprenderemos cómo extender la sintaxis de Galen con nuestro propio lenguaje, cómo mejorar el código de prueba y cómo convertir una rutina de prueba de diseño en arte.
Introducción a Galen Framework
Galen Framework se cubrió hace un año en "Desarrollo visual basado en pruebas para el diseño de interfaz sensible". En ese momento, su sintaxis era limitada. Ha mejorado mucho desde entonces y ha obtenido muchas características nuevas, que veremos aquí.
En caso de que no esté familiarizado con Galen Framework, es una herramienta para pruebas de diseño y pruebas funcionales receptivas y entre navegadores, con su propio lenguaje de prueba, llamado Galen Specs. Se basa en Selenium WebDriver y también tiene una rica API de JavaScript que le permite trabajar con WebDriver directamente. Debido a que tiene control sobre WebDriver, puede ejecutar pruebas en cualquier navegador, en la nube (SauceLabs, BrowserStack, PerfectoMobile, etc.) o en dispositivos móviles reales usando Appium.
Instalando y Ejecutando
Configurar Galen Framework es fácil. Simplemente ejecute el siguiente comando para instalarlo a través de npm:
npm install -g galenframework-cli
Si no usa npm, simplemente descargue el último archivo de Galen Framework, extraiga el paquete y siga las instrucciones de instalación.
Una vez instalado, Galen Framework se puede iniciar de varias maneras. Por ejemplo, puede usar el comando de check
para iniciar una prueba rápida de una sola página. Para este comando, debe proporcionar un archivo .gspec
con sus validaciones de diseño y luego puede invocarlo de esta manera:
galen check loginPage.gspec --url https://example.com --size 1024x768 --include desktop --htmlreport reports
Este comando iniciará un navegador, abrirá la URL especificada, cambiará el tamaño de la ventana del navegador a 1024 × 768 píxeles y ejecutará todas las validaciones declaradas en el archivo loginPage.gspec
. Como resultado, obtendrá un informe HTML detallado.
Gestión de conjuntos de pruebas
En el mundo real, una aplicación web real no consta únicamente de páginas estáticas. Muy a menudo tendrá que realizar algunas acciones para llegar al lugar que desea verificar. En este caso, Galen ofrece conjuntos de pruebas de JavaScript y la API de JavaScript de GalenPages para implementar el modelo de objetos de página. Aquí hay un ejemplo simple de una prueba Galen de JavaScript:
test("Home page", function() { var driver = createDriver("https://galenframework.com", "1024x768"); checkLayout(driver, "homePage.gspec", ["desktop"]); });
Y aquí hay una implementación del modelo de objeto de página para una página de inicio de sesión, tomada de un proyecto real.
WelcomePage = $page("Welcome page", { loginButton: "#welcome-page .button-login" }); LoginPage = $page("Login page", { username: "input[name='login.username']", password: "input[name='login.password']", loginButton: "button.button-login" loginAs: loggedFunction ("Log in as ${_1.username} with password ${_1.password}", function(user) { this.username.typeText(user.username); this.password.typeText(user.password); this.loginButton.click(); }) }); test("Login page", function() { var driver = createDriver("https://testapp.galenframework.com", "1024x768"); var welcomePage = new WelcomePage(driver).waitForIt(); welcomePage.loginButton.click(); new LoginPage(driver).waitForIt(); checkLayout(driver, "loginPage.gspec", ["desktop"]); });
Para un uso avanzado, le aconsejo que consulte el proyecto Galen Bootstrap. Es una extensión de JavaScript creada específicamente para Galen. Proporciona algunas funciones adicionales para las pruebas de interfaz de usuario y una forma más sencilla de configurar navegadores y ejecutar conjuntos de pruebas complejos.
Prueba de diseño simple
Permítanme comenzar presentando una prueba de diseño simple en Galen Framework. Luego, pasaré a casos de uso avanzados y demostraré cómo extender la sintaxis de Galen Specs. Para ello, nos fijaremos en un encabezado con un icono y una leyenda:

En código HTML, podría verse así:
<body> <!-- … --> <div> <img class="header-logo" src="/imgs/header-logo.png"/> <h1>My Blog</h1> </div> <!-- … --> </body>
La forma más simple de una prueba de diseño de Galen sería similar a la siguiente. Primero, tenemos que declarar objetos con selectores CSS.
@objects header #header icon #header img caption #header h1
Luego, declaramos una sección de prueba con un nombre significativo y colocamos todas nuestras validaciones debajo.
= Icon and Caption = icon: left-of caption 10 to 15px width 32px height 32px inside header 10px top caption: aligned horizontally all header inside header
Aquí hemos probado dos elementos de encabezado: el icono y el título. Todas las validaciones enumeradas bajo el ícono y los elementos de título son en realidad especificaciones estándar de Galen. Esas especificaciones son los bloques de construcción fundamentales con los que puede ensamblar su propia solución de prueba de diseño. Cada especificación verifica una sola propiedad (como ancho, alto, texto), posicionamiento relativo (como dentro, a la izquierda, arriba) o píxeles en la captura de pantalla (como combinación de colores, imagen).
Prueba de varios elementos mediante bucles forEach
El ejemplo anterior demuestra un escenario simple. Veamos cómo podemos lidiar con una situación más complicada: un menú horizontal. Primero, probemos una técnica de prueba de diseño sencilla.

Comience haciendo coincidir varios elementos en la página. Con el siguiente código, le estamos diciendo a Galen que busque elementos que coincidan con el selector CSS #menu ul li
.
@objects menu #menu item-* ul li
Más tarde, podemos referirnos a estos elementos con nombres como menu.item-1
y menu.item-2
e iterar sobre todos los elementos del menú usando un bucle @forEach
.
= Menu = menu.item-1: inside menu 0px top left bottom @forEach [menu.item-*] as menuItem, next as nextItem ${menuItem}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}
Como puede ver, aunque la verificación real no es tan compleja, el código ya se ha vuelto menos intuitivo. Imagínese si tuviéramos más código similar en nuestras pruebas. En algún momento, se convertiría en un desastre imposible de mantener. Debería haber una forma de mejorarlo.
Repensar las pruebas de diseño
Si piensa en el ejemplo anterior, parece que podríamos expresar el diseño en solo una o dos oraciones. Por ejemplo, podríamos decir algo como: “Todos los elementos del menú deben estar alineados horizontalmente, sin márgenes intermedios. El primer elemento del menú debe ubicarse en el lado izquierdo del menú, sin margen”. Debido a que hemos formulado oraciones para explicar el diseño que queremos, ¿por qué no podemos simplemente usarlas en nuestro código? Imagina si pudiéramos escribir el código así:
= Menu = |first menu.item-* is in top left corner of menu |menu.item-* are aligned horizontally next to each other
De hecho, ese es un código de trabajo real, copiado de mi proyecto. En esas dos últimas líneas (comenzando con la barra vertical, |
), estamos invocando funciones personalizadas que recopilan sus argumentos analizando esas dos declaraciones. Por supuesto, el ejemplo anterior no funcionará como está. Para que se compile, necesitamos implementar los controladores para esas dos declaraciones. Volveremos a esta implementación más adelante.
El punto clave del ejemplo anterior es que las pruebas de diseño han cambiado de pruebas basadas en objetos a pruebas basadas en expresiones . Puede que no sea obvio a partir de un ejemplo tan pequeño, pero definitivamente se nota a mayor escala. Entonces, ¿por qué es esto significativo? La respuesta corta es que esto cambia nuestra mentalidad y afecta la forma en que diseñamos nuestro software y escribimos pruebas para él.
Con esta técnica, no tratamos nuestra página como un grupo de objetos con relaciones específicas entre ellos. No probamos las propiedades CSS de elementos individuales. Y evitamos escribir código complicado no trivial. En cambio, estamos tratando de pensar en patrones de diseño comunes y declaraciones significativas. En lugar de probar el elemento de menú 1, el elemento de menú 2 y así sucesivamente por separado, aplicamos declaraciones genéricas que:
- son reproducibles en otros elementos;
- no contienen valores de píxeles codificados;
- se aplican a abstracciones y no a objetos concretos;
- y, por último, pero no menos importante, tienen sentido cuando los leemos.
Cómo funciona
Permítanme explicar el mecanismo de las expresiones de diseño personalizadas utilizando este sencillo ejemplo:

En este ejemplo, se supone que debemos verificar que el botón se extienda hasta el panel, sin margen en el lado izquierdo o derecho. Sin reglas personalizadas, podemos abordarlo de diferentes maneras, pero prefiero la siguiente solución:
button: inside some_panel 0px left right
El código anterior nos brinda la flexibilidad de declarar un margen personalizado en los lados y también prueba implícitamente que el botón está contenido completamente dentro del panel. La desventaja es que no es muy legible, por lo que voy a poner esta validación detrás del button stretches to some_panel
. Para que eso funcione, necesitamos escribir una regla personalizada como esta:
@rule %{elementName} stretches to %{parentName} ${elementName}: inside ${parentName} 0px left right
Eso es todo. Ahora podemos ponerlo en nuestra prueba en una sola línea:
| button stretches to some_panel
Como puede ver, esta regla toma dos argumentos: elementName
y parentName
. Esto nos permite aplicarlo a otros elementos también. Simplemente reemplace los nombres de esos dos objetos.
| login_panel stretches to main_container | header stretches to screen | footer stretches to screen # etc.
Implementación de su propio lenguaje de prueba
Volvamos a los ejemplos iniciales de expresiones de diseño para el menú horizontal.
= Menu = | first menu.item-* is in top left corner of menu | menu.item-* are aligned horizontally next to each other
Podemos implementar la primera regla de la siguiente manera:
@rule first %{itemPattern} is in %{cornerSides} corner of %{parentElement} @if ${count(itemPattern) > 0} ${first(itemPattern).name}: inside ${parentElement} 0px ${cornerSides}
Cuando se usa en nuestro ejemplo, analizaría los argumentos de la siguiente manera:
-
itemPattern
=menu.item-*
-
cornerSides
=top left
-
parentElement
=menu
Debido a que hemos terminado con nuestra primera expresión, podemos pasar a la siguiente. En la segunda expresión, se supone que debemos probar la alineación horizontal de todos los elementos del menú. Propongo tres sencillos pasos:
- Encuentra todos los elementos del menú.
- Iterar sobre todos ellos hasta el penúltimo elemento.
- Verifique que el elemento
n
esté ubicado a la izquierda del elementon+1
y que sus bordes superior e inferior estén alineados.
Para que funcione, necesitamos tomar un bucle @forEach
y especificaciones left-of
y aligned
. Afortunadamente, en Galen puede hacer referencia al elemento anterior o siguiente en un bucle. En caso de que hayas declarado una referencia al siguiente elemento, iterará solo hasta el penúltimo elemento, que es exactamente lo que necesitamos.
@rule %{itemPattern} are aligned horizontally next to each other @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}
Podría preguntar: ¿Qué pasa si tenemos que especificar un margen en nuestra prueba (como ~ 20px
o 10 to 20px
)? Luego, sugiero implementar una regla separada o extender la existente para admitir un argumento %{margin}
.
@rule %{itemPattern} are aligned horizontally next to each other with %{margin} margin @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} ${margin} aligned horizontally all ${nextItem}
¡Eso es todo! Hemos creado una expresión genérica que nos ayuda a validar el menú horizontal. Sin embargo, debido a su flexibilidad, podemos hacer mucho más que eso. Podemos usarlo para probar cualquier otro elemento en la página. Incluso podemos usarlo para probar la alineación de dos botones:

| menu.item-* are aligned horizontally next to each other with 0px margin | submit_button, cancel_button are aligned horizontally next to each other with 20px margin
Puede notar en estos dos ejemplos que hemos declarado el primer argumento de dos maneras diferentes. En la primera expresión, el primer argumento es “menu.item-*”
y en la segunda expresión se declara como “submit_button, cancel_button”
. Eso es posible porque el ciclo @forEach
nos permite usar una lista de objetos separados por comas junto con el operador estrella. Pero todavía no hemos terminado con la refactorización. Podríamos mejorar aún más el código y hacerlo más legible. Si creamos grupos para los elementos del menú y los botones del formulario de inicio de sesión, podríamos lograr algo como esto:

@groups menu_items menu_item-* login_form_buttons submit_button, cancel_button = Testing login page = | &menu_items are aligned horizontally next to each other with 0px margin | &login_form_buttons are aligned horizontally next to each other with 20px margin
En este caso, tenemos que usar el símbolo &
, que representa una declaración de grupo. Eso ya es una buena prueba. Primero, simplemente funciona y podemos probar lo que necesitamos. Además, el código es claro y legible. Si otra persona le preguntara cómo debería verse la página de inicio de sesión y cuáles son los requisitos de diseño, podría decirle que mire la prueba.
Como puede ver, implementar expresiones personalizadas para patrones de diseño complejos no es gran cosa. Puede ser un desafío al principio, pero aún se parece a una actividad creativa.
Márgenes dinámicos
Veamos otro patrón de diseño raro que puede encontrar a veces en varios sitios web. ¿Qué pasaría si quisiéramos probar que los elementos tienen la misma distancia entre sí? Intentemos implementar otra regla para eso, pero esta vez usando una implementación de JavaScript. Propongo tal declaración: “box_item-* are aligned horizontally next to each other with equal distance”
. Esto va a ser un poco complicado porque no conocemos el margen entre los elementos y no podemos simplemente codificar valores de píxeles. Por lo tanto, lo primero que tenemos que hacer es recuperar el margen real entre el primer y el último elemento.

Una vez que obtengamos ese margen, podemos declararlo en un bucle @forEach
similar a como lo hicimos antes. Propongo implementar esta regla usando la API de JavaScript porque la lógica requerida es un poco más compleja que en todos nuestros ejemplos anteriores. Vamos a crear un archivo llamado my-rules.js
y escribir este código:
rule("%{objectPattern} are aligned horizontally next to each other with equal margin", function (objectName, parameters) { var allItems = findAll(parameters.objectPattern), distance = Math.round(Math.abs(allItems[1].left() - allItems[0].right())), expectedMargin = (distance - 1) + " to " + (distance + 1) + "px"; if (allItems.length > 0) { for (var i = 0; i < allItems.length - 1; i += 1) { var nextElementName = allItems[i + 1].name; this.addObjectSpecs(allItems[i].name, [ "aligned horizontally all " + nextElementName, "left-of " + nextElementName + " " + expectedMargin ]); } } });
En nuestro código de prueba, lo usaremos así:
@script my-rules.js # … = Boxes = | box_item-* are aligned horizontally next to each other with equal distance
Como puedes ver, en Galen Framework podemos elegir entre dos lenguajes a la hora de implementar las reglas: Galen Specs y JavaScript. Para expresiones simples, Galen Specs es más fácil de usar, pero para las complejas siempre elijo JavaScript. Si desea obtener más información sobre las reglas de JavaScript, consulte la documentación.
Extras de Galeno
Habiendo jugado lo suficiente con varios patrones de diseño, me di cuenta de que todas estas reglas de Galen podrían aplicarse fácilmente en cualquier otro proyecto de prueba. Eso me dio una idea para compilar las expresiones de diseño más comunes en su propia biblioteca. Así fue como llegué a crear el proyecto Galen Extras. A continuación se muestran algunos ejemplos de lo que esta biblioteca es capaz de hacer:
| header.icon should be squared | amount of &menu_items should be > 3 | &menu_items are aligned horizontally next to each other | &list_items are aligned vertically above each other with equal distance | every &menu_item is inside menu 0px top and has width > 50px | first &menu_item is inside menu 0px top left | &menu_items are rendered in 2 column table | &menu_items are rendered in 2 column table, with 0 to 1px vertical and 10px horizontal margin | &login_form_elements sides are vertically inside content_container with 20px margin login_panel: | located on the left side of panel and takes 70 % of its width # etc …
La biblioteca Galen Extras contiene muchos de los patrones de diseño que encontraría comúnmente en los sitios web, y sigo actualizándola tan pronto como descubro un patrón útil. Una vez que se configuró esta biblioteca, decidí probarla en un proyecto de prueba real.
Prueba de la aplicación de mensajería
Actualmente, trabajo como ingeniero de software en Marktplaats. En algún momento, decidí aplicar toda la experiencia que había adquirido a un proyecto real. Necesitaba probar la página de mensajería en nuestro sitio web. Esto es lo que parece:

Para ser honesto, implementar pruebas para tales páginas siempre me ha parecido un poco aterrador, especialmente las pruebas de diseño. Pero con la biblioteca Galen Extras en su lugar, en realidad funcionó bastante bien, y pronto pude generar este código:
@import ../selected-conversation.gspec @groups (message, messages) messenger.message-* first_two_messages messenger.message-1,messenger.message-2 first_message messenger.message-1 second_message messenger.message-2 third_message messenger.message-3 (message_date_label, message_date_labels) messenger.date_label-* first_date_label messenger.date_label-1 second_date_label messenger.date_label-2 = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ~ 20px margin |&third_message should be located at the right inside messenger with ~ 20px margin |&messages are placed above each other with 10 to 15px margin |text of all &messages should be ["Hi there!", "I want to buy something", "Hello! Sure, it's gonna be 100 euros"] = Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message
Extracción de rangos de píxeles
La prueba se veía bien: era compacta y legible, pero aún estaba lejos de ser perfecta. Realmente no me gustaron todas esas definiciones de márgenes ( ~ 20px
, 10 to 15px
). Algunos de ellos se repetían, y era difícil entender lo que representaba cada uno de ellos. Por eso decidí ocultar cada margen detrás de una variable significativa.
# ... @set messages_side_margin ~ 20px messages_vertical_margin 10 to 15px = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ${messages_side_margin} margin |&third_message should be located at the right inside messenger with ${messages_side_margin} margin |&messages are placed above each other with ${messages_vertical_margin} margin # ...
Como puede ver, moví los márgenes a messages_vertical_margin
y messages_side_margin
. También he declarado un margen minimal
, que es un rango entre 0 y 1 píxel.
# ... @set minimal 0 to 1px = Conversations Panel = | &conversations are aligned above each other with ${minimal} margin # ...
Validación basada en imágenes y expresiones personalizadas
Habiendo cubierto el posicionamiento de todos los elementos principales en la página, decidí probar también el estilo. Quería validar que cada mensaje tenga un color de fondo específico para el rol del usuario. Cuando los usuarios inician sesión, los mensajes tendrán un fondo azul claro. Los mensajes para otros usuarios tendrían un fondo blanco. En caso de que no se haya enviado un mensaje, la alerta de error tendría un fondo rosa. Aquí está la regla que me ayudó a validar estos estilos:
@set OWN_MESSAGE_COLOR #E1E8F5 OTHERS_MESSAGE_COLOR white ERROR_MESSAGE_COLOR #FFE6E6 @rule %{item} should be styled as %{style} message ${item}: @if ${style === "own"} color-scheme > 60% ${OWN_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @elseif ${style === "error"} color-scheme > 60% ${ERROR_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @else color-scheme > 60% ${OTHERS_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR}
La especificación color-scheme
verifica la distribución proporcional de colores dentro de un elemento. Recorta una captura de pantalla de la página y analiza la distribución del color. Entonces, para verificar el color de fondo de un elemento, solo verificamos que su distribución sea mayor al 60% del rango total de colores. En la prueba, esta regla se invoca así:
= Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message
Configuración de conjuntos de pruebas
La aplicación de mensajería es una aplicación dinámica que funciona junto con la API de mensajería RESTful. Por lo tanto, para probar sus diseños en todos los estados diferentes, tenemos que preparar datos de prueba. Decidí simular la API de mensajería para poder configurar todos mis mensajes de prueba en el conjunto de pruebas. Aquí hay un fragmento de mi conjunto de pruebas que muestra cómo se estructuran nuestras pruebas.
// ... testOnAllDevices("Unselected 2 conversations", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); refresh(driver); new MessageAppPage(driver).waitForIt(); checkLayout(driver, "specs/tests/unselected-conversations.gspec", device.tags); }); testOnAllDevices("When clicking a conversation it should reveal messages", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); mock.onGetSingleConversationReturn(sampleMessages); refresh(driver); var page = new MessageAppPage(driver).waitForIt(); page.clickFirstConversation(); checkLayout({ driver: driver, spec: "specs/tests/three-simple-messages-test.gspec", tags: device.tags, vars: { expectedTextProvider: textProvider({ "messenger.message-1": "Hi there!\n11:02", "messenger.message-2": "I want to buy something\n12:02", "messenger.message-3": "Hello! Sure, it's gonna be 100 euros\n13:02" }) } }); }); // ...
Atrapar insectos
La implementación de esas expresiones simples vale la pena con bastante rapidez. Repasemos qué tipo de errores podemos detectar con nuestro conjunto de pruebas.
Problema de estilo
Aquí hay un ejemplo de cuando algo sale mal en nuestra base de código CSS y, como resultado, todos los mensajes se representan con el mismo fondo.

Si compara esta captura de pantalla con la original, notará que el último mensaje tiene un fondo blanco, mientras que se supone que es azul claro. Veamos cómo informa Galen este problema:

Para el objeto resaltado, muestra el color #e1e8f5 on “messenger.message-3” is 0% but it should be greater than 60%
. Para ser honesto, este mensaje de error no parece tan claro, pero debido a que esta verificación se generó a partir de una regla personalizada, siempre podemos buscar su nombre original en una rama del informe:

Si se desplaza hacia arriba, verá que la declaración original es &third_message should be styled as own message
. Ese es otro beneficio de usar expresiones personalizadas: lo ayudan a comprender la falla y describen muy bien todas esas validaciones generadas.
Problema de posicionamiento
Aquí hay otro ejemplo de cuando el diseño sale mal debido a la alineación incorrecta de un elemento. En la siguiente captura de pantalla, puede ver que el último mensaje está ubicado en el lado izquierdo de la ventana gráfica de mensajes, en lugar del derecho.

Miremos nuevamente la captura de pantalla con el mensaje de error:

La captura de pantalla resalta el contenedor de mensajes y el último elemento del mensaje. Junto con eso, muestra el siguiente mensaje de error: “messenger.message-3” is 285px right which is not in range of 22 to 28px
. Es posible que un desarrollador web no tenga claro por qué se espera un margen de 22 a 28 píxeles en el lado derecho. Nuevamente, tendría que buscar una declaración de validación en la rama del informe:

La declaración original para esa verificación es &third_message should be located at the right inside messenger with ~ 25px margin
. Eso tiene mucho más sentido. Además, otros ingenieros front-end comprenderán este informe de prueba, incluso si no han escrito las pruebas.
Pautas de prueba de diseño
Con todos estos diferentes experimentos en mente, decidí formalizar todo el aprendizaje en pautas generales de prueba de diseño. Aquí hay una lista de verificación rápida de los pasos a seguir para facilitar su rutina de prueba.
- Identificar patrones de disposición en el diseño.
- Generalizar declaraciones de validación. Trate de condensar la mayoría de las validaciones en oraciones individuales.
- ¡Componentiza! Siempre es mejor mover las pruebas de elementos repetidos a componentes dedicados.
- Use nombres significativos para secciones, reglas y objetos.
- Evita los píxeles. Intente reemplazar los valores de píxeles (ya sean valores exactos o rangos) con variables significativas.
- Ajuste el código de su sitio web para que sea más fácil de probar. Esto lo ayudará a estructurar y mantener tanto su código de producción como el de prueba.
Criterios de aceptación Al rescate
A menudo recibo preguntas como: “¿Qué tan detallada debe ser una prueba de diseño? ¿Y qué deberíamos estar probando específicamente? Es difícil dar una respuesta general. El problema es que cuando la cobertura de la prueba es pequeña, se pierden errores. Por otro lado, si tiene pruebas demasiado detalladas, puede obtener muchos falsos positivos y, en el futuro, perderse en el mantenimiento de las pruebas. Entonces, hay una compensación. Pero me di cuenta de una pauta general para mí. Si divide el trabajo en historias de usuario más pequeñas, será más fácil estructurar el diseño de una página en forma de criterios de aceptación. Al final, puede poner este mismo criterio de aceptación en su código de prueba. Por ejemplo, algunas de estas declaraciones podrían definirse en forma de reglas personalizadas, como se muestra en todos los ejemplos de código anteriores. Un buen ejemplo de criterios de aceptación sería algo como esto:
- Las ventanas emergentes deben estar centradas vertical y horizontalmente en la pantalla.
- Deben tener 400 píxeles de ancho.
- Los botones deben estar alineados horizontalmente.
- Y así
Una vez que describa el diseño en oraciones simples, será más fácil convertirlas en declaraciones reutilizables y organizar su código de prueba.
Conclusión
Como puede ver, este ejercicio lo ayuda a estructurar un diseño y descubrir patrones de diseño generales que se pueden compartir entre varios componentes de página. Incluso si la página es compleja y consta de muchos elementos, siempre puede encontrar una manera de agruparlos en sus expresiones de diseño. Con este enfoque, las pruebas de diseño se convierten más en una herramienta para el desarrollo basado en pruebas, lo que lo ayuda a diseñar, implementar y entregar software de forma incremental, lo que es especialmente útil en un entorno ágil.
Recursos
- Galen Framework (sitio web oficial)
- Marco Galeno, GitHub
- Extras de Galen (biblioteca), GitHub
- Galeno Bootstrap, GitHub
- "Tutoriales de Galen Framework", YouTube