paint-brush
Los cuatro jinetes de las pruebas escamosasby@truuts
1,333
1,333

Los cuatro jinetes de las pruebas escamosas

Eugene Truuts6m2023/10/24
Read on Terminal Reader

Las pruebas de automatización inestables pueden ser una pesadilla para los ingenieros de control de calidad, ya que introducen incertidumbre y socavan la confiabilidad de los conjuntos de pruebas. A partir de mi experiencia como mentor de SDET y QA Automation, este artículo ofrece consejos prácticos para superar la debilidad. Si bien proporcionaré ejemplos de JavaScript y Playwright, estos consejos universales son aplicables en cualquier lenguaje y marco y lo ayudarán a escribir pruebas de automatización sólidas y confiables. Profundicemos y asegurémonos de que sus pruebas se mantengan firmes.
featured image - Los cuatro jinetes de las pruebas escamosas
Eugene Truuts HackerNoon profile picture
0-item
1-item


Las pruebas de automatización inestables pueden ser una pesadilla para los ingenieros de control de calidad, ya que introducen incertidumbre y socavan la confiabilidad de los conjuntos de pruebas. A partir de mi experiencia como mentor de SDET y QA Automation, este artículo ofrece consejos prácticos para superar la debilidad. Si bien proporcionaré ejemplos de JavaScript y Playwright, estos consejos universales son aplicables en cualquier lenguaje y marco, y lo ayudarán a escribir pruebas de automatización sólidas y confiables. Profundicemos y asegurémonos de que sus pruebas se mantengan firmes.

1. Evite los métodos de espera implícitos

Ocasionalmente, encontrará situaciones en las que deberá esperar a que aparezcan elementos en el DOM o a que su aplicación alcance un estado específico para continuar con su escenario de prueba. Incluso con marcos de automatización modernos e inteligentes, como las funciones de espera automática de Playwright, habrá casos en los que será necesario implementar métodos de espera personalizados. Por ejemplo, considere un escenario con campos de texto y un botón de confirmación. Debido al comportamiento específico del lado del servidor, el botón de confirmación se vuelve visible solo después de aproximadamente cinco segundos de completar el formulario. En tales casos, es esencial resistir la tentación de insertar una espera implícita de cinco segundos entre dos pasos de la prueba.


 textField.fill('Some text') waitForTime(5000) confirmationButton.click()


En su lugar, utilice un enfoque inteligente y espere el estado exacto. Puede ser el elemento de texto que aparece después de alguna carga o un elemento giratorio del cargador que desaparece después de que el paso actual se realiza con éxito. Puede comprobar si está listo para el siguiente paso de la prueba.


 button.click() waitFor(textField.isVisible()) textField.fill()


Por supuesto, hay casos en los que hay que esperar por algo que no se puede comprobar de forma inteligente. Sugiero agregar comentarios en dichos lugares o incluso agregar la explicación del motivo como parámetro en sus métodos de espera o algo así:


 waitForTime(5000, {reason: "For unstable server processed something..."}


Una ventaja adicional de usarlo son los informes de prueba, donde puede almacenar dichas explicaciones para que sea obvio para otra persona o incluso para usted en el futuro qué y por qué esa espera de cinco segundos aquí.


 waitForTime(5000, {reason: "For unstable server processed something..."} button.click() waitFor(textField.isVisible()) textField.fill()

2. Utilice localizadores robustos y confiables para seleccionar elementos

Los localizadores son una parte crucial de las pruebas de automatización y todo el mundo lo sabe. Sin embargo, a pesar de este simple hecho, muchos ingenieros de automatización están renunciando a la estabilidad y utilizando algo como esto en sus pruebas.


 //*[@id="editor_7"]/section/div[2]/div/h3[2]


Este es un enfoque tonto porque la estructura DOM no es tan estática; A veces, algunos equipos diferentes pueden cambiarlo, y esto después de que las pruebas fallan. Entonces, use los localizadores robustos. Por cierto, eres bienvenido a leer mi historia relacionada con XPath.



3.Hacer pruebas independientes entre sí.

Al ejecutar el conjunto de pruebas con varias pruebas en un solo subproceso, es fundamental garantizar que cada prueba sea independiente. Esto significa que la primera prueba debe devolver el sistema a su estado original para que la siguiente prueba no falle debido a condiciones inesperadas. Por ejemplo, si una de sus pruebas modifica la configuración de usuario almacenada en LocalStorage, borrar la entrada de LocalStorage para Configuración de usuario después de las primeras ejecuciones de prueba es un buen enfoque. Esto garantiza que la segunda prueba se ejecutará con la configuración de usuario predeterminada. También puede considerar acciones como restablecer la página a la página de entrada predeterminada y borrar las cookies y las entradas de la base de datos para que cada nueva prueba comience con condiciones iniciales idénticas.


Por ejemplo, en Playwright, puedes usar las anotaciones beforeAll(), beforeEach(), afterAll() y afterEach() para lograrlo.


Consulte el próximo conjunto de pruebas con un par de pruebas. El primero es cambiar la configuración de apariencia del usuario y el segundo es verificar la apariencia predeterminada.


 test.describe('Test suite', () => { test('TC101 - update appearance settings to dark', async ({page}) => { await user.goTo(views.settings); await user.setAppearance(scheme.dark); }); test('TC102 - check if default appearance is light', async ({page}) => { await user.goTo(views.settings); await user.checkAppearance(scheme.light); }); });


Si dicho conjunto de pruebas se ejecuta en paralelo, todo irá bien. Sin embargo, si estas pruebas se ejecutan una por una, podría enfrentar una prueba fallida porque una de ellas interfiere con la otra. La primera prueba cambió la apariencia de clara a oscura. La segunda prueba comprueba si la apariencia actual es clara. Pero fallará ya que la primera prueba ya cambió la apariencia predeterminada.

Para resolver este problema, agregué el gancho afterEach() que se ejecuta después de cada prueba. En este caso, navegará a la vista predeterminada y borrará la apariencia del usuario eliminándolo del Almacenamiento local.


 test.afterEach(async ({ page }) => { await user.localStorage(appearanceSettings).clear() await user.goTo(views.home) }); test.describe('Test suite', () => { test('TC101 - update appearance settings to dark', async ({page}) => { await user.goto(views.settings); await user.setAppearance(scheme.dark); }); test('TC102 - check if default appearance is light', async ({page}) => { await user.goTo(views.settings); await user.checkAppearance(scheme.light); }); });


Con este enfoque, cada prueba de este conjunto será independiente.


4. Utilice los reintentos automáticos con prudencia

Nadie es inmune a encontrarse con pruebas fallidas y un remedio popular para este problema implica el uso de reintentos. Puede configurar los reintentos para que se realicen automáticamente, incluso en el nivel de configuración de CI/CD. Por ejemplo, puede configurar reintentos automáticos para cada prueba fallida, especificando un recuento máximo de reintentos de tres veces. Cualquier prueba que falle inicialmente se volverá a intentar hasta tres veces hasta que se complete el ciclo de ejecución de la prueba. La ventaja es que si su prueba es ligeramente inestable, puede pasar después de un par de reintentos.


Sin embargo, la desventaja es que podría fallar, lo que provocaría un consumo adicional de tiempo de ejecución. Además, esta práctica puede conducir inadvertidamente a una acumulación de pruebas inestables, ya que muchas pruebas pueden parecer "aprobadas" en el segundo o tercer intento, y usted podría etiquetarlas incorrectamente como estables. Por lo tanto, no recomiendo configurar reintentos automáticos globalmente para todo el proyecto de prueba. En su lugar, utilice los reintentos de forma selectiva en los casos en los que no pueda resolver rápidamente los problemas subyacentes de la prueba.


Por ejemplo, imagina que tienes un caso de prueba en el que debes cargar algunos archivos usando el evento 'filechooser'. Aparece el error <Tiempo de espera excedido mientras se espera el evento 'filechooser'>, lo que indica que la prueba de Playwright está esperando a que ocurra un evento 'filechooser' pero está tardando más tiempo de espera.


 async function uploadFile(page: Page, file) { const fileChooserPromise = page.waitForEvent('filechooser'); await clickOnElement(page, uploadButton); const fileChooser = await fileChooserPromise; await fileChooser.setFiles(file); }


Esto puede deberse a varios motivos, como un comportamiento inesperado en la aplicación o un entorno lento. Debido a que se trata de un comportamiento aleatorio, lo primero que podría pensar es en utilizar el reintento automático para esta prueba. Sin embargo, si vuelve a intentar toda la prueba, corre el riesgo de perder más tiempo y obtener el mismo comportamiento que obtuvo con el primer error en el método uploadFile(), por lo que si ocurre el error, no necesita volver a intentar toda la prueba.


Para hacer esto, puede usar la declaración estándar try...catch.


 async function uploadFile(page: Page, file) { const maxRetries = 3; let retryCount = 0; while (retryCount < maxRetries) { try { const fileChooserPromise = page.waitForEvent('filechooser'); await clickOnElement(page, uploadButton); const fileChooser = await fileChooserPromise; await fileChooser.setFiles(file); break; // Success, exit the loop } catch (error) { console.error(`Attempt ${retryCount + 1} failed: ${error}`); retryCount++; } } }


Este enfoque ahorrará tiempo adicional y hará que la prueba sea menos complicada.


Para terminar, el camino hacia pruebas de automatización confiables es sencillo. Puede minimizar o abordar activamente los desafíos comunes e implementar estrategias inteligentes. Recuerde, este viaje es continuo y sus pruebas serán más confiables con perseverancia. Dile adiós a la descamación y dale la bienvenida a la estabilidad. Su compromiso con la calidad garantiza el éxito del proyecto. ¡Feliz prueba!


También publicado aquí .