Cómo tuve que convertirme en una pequeña automatización qa: lo que sentí, sobreviví y la maravillosa arquitectura e infraestructura de las pruebas automáticas a través de los ojos de un desarrollador que pasaba.
Introduccion
Como dicen, no soy ginecólogo, simplemente pasé y decidí mirar. Por lo tanto, para empezar, diré sobre las razones para escribir. Me parece que un especialista haría frente al problema un orden de magnitud más rápido y no recogería tantos rastrillos en su camino. Pero él no estaría tan interesado como yo, y no tendrías nada que leer.
Otra razón que me llevó a escribir: durante bastante tiempo no entendí qué tenía de especial la infraestructura de las pruebas automáticas. Además, muchos gerentes de PM y superiores tampoco entendieron completamente lo que es tan cósmico allí y por qué los desarrolladores escriben pruebas unitarias para uno o dos, y para las pruebas de phycestest, se toman individuos individuales, que escriben pruebas más lentamente, constantemente reparan algo y La posibilidad de aprobar todas las especificaciones financieras es estrictamente inferior al 100%, siempre que la muestra sea lo suficientemente grande.
El problema
Al tercer día, la especificación del problema en el proyecto ferroviario cayó. Aproximadamente una semana antes, nuestro único ingeniero de automatización decidió ir a trabajar a Chicago y aún no hemos encontrado un nuevo especialista. Por lo tanto, tuve que arremangarme y pretender ser QA. Sobre cómo fue y trato de contarlo.
El problema parece bastante inofensivo. Pero, para empezar, un poco de historia y descripción del entorno. Tenemos muchos selectores de direcciones en nuestra plataforma. Honestamente, esta es una de las principales entidades de la plataforma. Los selectores van a la API de Google para obtener datos. En las pruebas automáticas, todas las solicitudes se estancan para ahorrar dinero y acelerar las pruebas. Además, se ha agregado un poco de lógica para proporcionar aproximadamente la misma línea de dirección que se solicitó sin ir a servicios externos.
Lo que se ha roto: ingresamos la dirección deseada en la barra de direcciones, aparece un cuadro desplegable con varias opciones, seleccionamos la deseada y ... el valor del elemento vecino se inserta en la entrada. Siempre.
Un largo camino hacia la verdad
Primeras hipótesis y enfoque ingenuo.
Sin más dilación, tomé la prueba de caída más cercana, encontré la línea en la que se seleccionó la dirección y comencé a examinarla cuidadosamente y a los vecinos. La línea parece inofensiva: new_order_page.destination_address.select(baker_street)
. Pero entendemos que detrás de un código hermoso siempre hay un montón de pequeños diseños extraños y entrañas desagradables.
Rápidamente recordé que toda esta economía funciona en SitePrism . Esto hace posible ajustar la página y los elementos en la clase y los métodos de clase, respectivamente. Para los clics y otras acciones, Capybara y RSpec son responsables. Pero no tienen dudas, son confiables, como toda la flota civil. Y si es así, la primera hipótesis se sugiere de inmediato: alguien escribió mal los selectores para el prisma o alguien torció el diseño en la parte delantera.
La primera parte de la hipótesis desapareció rápidamente, los selectores se escriben perfectamente. No se encontró ningún xpath
con la elección del tercer li
dentro del elemento y el código en sí no cambió el año pasado.
Sin embargo, en el área del método de select
, se apiló la lógica con expresiones regulares para seleccionar la opción deseada de la lista desplegable. Por supuesto, me enojo con las expresiones regulares y voy a revisarlas. Paso media hora y entiendo que todo funciona bien. Se selecciona exactamente la línea que se necesita. click
en él. Y todo debería funcionar. Es decir, la segunda parte de la hipótesis del diseño también desaparece. Pero el pensamiento aparece sobre la curva js
. Después de todo, el elemento en la página que tenemos es personalizado, js
organizan js
alrededor de él y, además, en este js
estado seleccionando.
Js tiene la culpa
Esta es la razón estándar para todos los problemas oscuros. Algo así como "ve a js
, porque ya está conmocionado". Y, al parecer, en mi caso, tampoco podría prescindir de js
. En general, sin pensarlo dos veces, corro hacia el equipo de front-end y apunto con el dedo a las pruebas de caída, declarando que "todo funciona de nuestro lado, por favor repare su lado".
Pero, los muchachos del dandy no son una señorita, eligen allí por un par de horas, encuentran un par de errores que no están relacionados con la narrativa y dicen que ¡ js
no tiene la culpa! Al mismo tiempo, arrojan información interesante de que una solicitud para la selección no es suficiente y él hace otra, cuya respuesta coincide exactamente con el contenido incorrecto de la entrada.
No esperaba tal giro. Tenemos que volver y descubrir cómo funciona la simulación de solicitudes para nosotros.
Enfoque integral
Entonces, no hay otro lugar para esperar ayuda, Moscú está detrás de nosotros y cosas así.
En primer lugar, analizamos las formas en que Moka solicita a Google. Más precisamente, primero buscamos dónde sucede esto. Esta no es una tarea trivial. Resulta que tenemos un módulo completo MockServices::Base
, que es responsable de la simulación de diferentes solicitudes usando VCR . Él está arrodillado astutamente en el controlador base y solo por el nombre del servicio responsable de las solicitudes externas, no se lo puede encontrar.
Bien, encontré el moki. Ahora miramos su implementación. La primera solicitud se moja simplemente: la información de los params
se toma y se sustituye en la plantilla con la respuesta. Por si acaso, verifiqué el contenido de los params
y, como era de esperar, todo sale como debería.
El método moka de la próxima solicitud es más interesante. Aparece algún tipo de mock_data
allí. Estos no son params
y tenemos que averiguar de dónde viene esta fecha. Habiendo caído cinco veces en profundidad, se revela que estos datos se toman de RequestStore usando la clave x_mock_data
. Ya más interesante.
Volvemos a la prueba original y notamos que hay una cosa set_mock_header
que, después de un examen más detallado, agrega algunos datos al mismo RequestStore
. Más interesante!
En algún lugar en este momento, se produce una disonancia cognitiva en la cabeza: por un lado, es la causa probable del problema, las variables globales que nos da la solicitud secundaria se han roto. Pero hay un matiz: el servidor para las especificaciones financieras y las especificaciones financieras en sí son dos procesos independientes (de hecho, el servidor tiene al menos 3 procesos), por lo tanto, un débito con crédito no puede converger de ninguna manera, porque todavía no se han introducido variables globales entre los procesos en este mundo. Y con un servidor web multiproceso, será un juego feroz, que no funcionará físicamente. Significa que ahuequé algo y es necesario buscar.
Miramos más allá y encontramos una cierta bm
, a la que los encabezados dejan. Continúa y date cuenta de que bm
es BrowserMob . Luego me puse un poco alterado, ya que es un proxy en Java en un contenedor de rubíes. Solo un piano en los arbustos.
Comenzamos a elegir más y entendemos que para las variables "globales" entre el cliente con rspec
y el servidor con la aplicación (por ejemplo, puma ), se utilizan los mismos encabezados X-Mock-Data
en la solicitud. El problema es que la aplicación no debe saber nada sobre estos lectores. Solo para esto, necesita un proxy a través del cual todas las solicitudes volarán y que se encargará de configurar los encabezados. Con astucia, no dirás nada.
Vamos a probar y descubrimos que solo esto no funciona. No se ven encabezados por ninguna parte: ni en las solicitudes ni en las respuestas. Pero RequestStore se llena en el lado rspec
y está vacío en el lado del servidor web. Eso significa con seguridad, está en el proxy.
Luego, en el medio, resulta que no solo tenemos pruebas con direcciones set_mock_header
, sino también todo lo que usa el set_mock_header
anterior.
Genial Queda por entender cómo solucionar esto.
Nos ocupamos de un proxy
Omitimos los puntos de excavación en la región donde se inicia el archivo jar
y luego lo controlamos a través de Ruby. Mejor preste atención a la forma en que se especifica el proxy del navegador. Usamos Chrome y pasamos información de proxy en uno de los muchos argumentos de la línea de comando cuando se inicia. La característica de proxy es que usamos el archivo pac
que generamos a partir de la plantilla para que el proxy no permita el tráfico de los sockets web.
En algún lugar aquí hay un deseo de ir y googlear lo que hay en Chrome con la configuración del proxy. Resulta que no tienes que ir muy lejos y en la versión 72+ los chicos "terminaron" su trabajo. En esta ocasión, incluso trajeron un error por separado . Mi comentario favorito
"¿Puede por favor dejar de ELIMINAR la funcionalidad?"
La tristeza es que se considera una característica y en el futuro prometen aún más estaño en términos de "secreto".
En resumen, Chrome ya no admite el file:
protocolo en el argumento proxy-pac-url
. Las soluciones son una mejor que la otra:
- Pase el argumento
js
, que leerá el archivo pac
y lo convertirá en base64: --proxy-pac-url='data:application/x-javascript-config;base64,'$(base64 -w0 /path/to/pac/script)
; - elevar su servidor web en python para distribuir un archivo de acuerdo con un protocolo más "correcto", que es compatible con el argumento para
pac
proxy; - apague
NetworkService
y luego el file:
protocolo debería funcionar, pero prometen que también será "reparado" en el futuro.
Las dos primeras opciones ciertamente no me inspiraron, y la tercera, curiosamente, ayudó.
Alegría de corta duración
Regocijándome de que se haya encontrado una conexión complicada entre los menús desplegables inactivos y Chrome actualizado, no estuve contento por mucho tiempo. Resulta que nuestro CI actualizó no solo Chrome, sino también todos los paquetes adyacentes, y ahora tenemos aún más pruebas que Selenium::WebDriver::Error::NoSuchDriverError
debido a un error desconocido Selenium::WebDriver::Error::NoSuchDriverError
, que, curiosamente, no está relacionado con el controlador de cromo , pero está relacionado con una configuración de Chrome, versiones de biblioteca y ejecución de especificaciones paralelas.
Pero esta es la tarea para el próximo día hábil ...
Mirando hacia el futuro: el argumento disable-dev-shm-usage
ayudó allí.
Conclusiones
No regañe a la automatización. Parece sufrir más por circunstancias externas que son independientes de él.
Es mejor hacerse amigo del ingeniero de automatización con los desarrolladores, para que organicen su infraestructura. con preferencia y cortesanas con versiones fijas y un entorno de prueba controlado. Para mí, esto es mejor que sufrir CI patentado, cada uno de los cuales tiene sus propias muletas y heces subacuáticas muy sofisticadas, de las que aprenderá solo después de una estrecha integración de su aplicación y pruebas con el entorno de otra persona.