En lugar de 100 lanzamientos de aplicaciones, una prueba automática o cómo salvar a un ingeniero de control de calidad 20 años de vida

Hola a todos, mi nombre es Evgeny Demidenko. Durante los últimos años, he estado desarrollando un sistema automatizado de prueba de juegos en Pixonic. Hoy quería compartir nuestra experiencia en el desarrollo, soporte y uso de dicho sistema en el proyecto War Robots.

Para empezar, descubriremos qué estamos automatizando con este sistema.

En primer lugar, estas son las pruebas de regresión de la interfaz de usuario, las pruebas del juego central y la automatización de los puntos de referencia. Los tres sistemas en su conjunto permiten reducir la carga del departamento de control de calidad antes de los lanzamientos, tener más confianza en la refactorización a gran escala y profunda, y mantener constantemente una evaluación general del rendimiento de la aplicación, así como de sus partes individuales. Otro punto que quiero señalar es la automatización de la rutina, por ejemplo, la prueba de cualquier hipótesis.

imagen

Daré algunos números. Ahora se han escrito más de 600 pruebas de IU y alrededor de 100 pruebas de núcleo para War Robots. Solo en este proyecto, realizamos alrededor de un millón de lanzamientos de nuestros scripts de prueba, cada uno de los cuales tomó aproximadamente 80 segundos. Si verificamos estos escenarios manualmente, hubiéramos pasado al menos cinco minutos cada uno. Además, lanzamos más de 700 mil puntos de referencia.

De las plataformas, usamos Android e iOS, solo 12 dispositivos en el parque. Dos programadores participan en el desarrollo y soporte del sistema, y ​​un ingeniero de control de calidad está escribiendo y analizando pruebas.






En cuanto a la pila de software, utilizamos NUnit en nuestra base de datos, pero no para pruebas unitarias, sino para pruebas de integración y sistema. Para el juego central y las pruebas de verificación de compilación, utilizamos la solución incorporada de Unity: Unity Test Tools. Para escribir y analizar informes después de estas pruebas, se utiliza el Informe de prueba Allure de Yandex, así como TeamCity , como un sistema de integración continua para la creación de aplicaciones, la implementación del servidor y las pruebas de ejecución. Utilizamos el repositorio Nexus y la base de datos PostgreSQL para almacenar nuestros artefactos.




¿Cómo se crean, analizan y ejecutan pruebas?


Supongamos que queremos escribir una prueba simple que en la ventana de configuración del juego verificará el icono para encender y apagar el sonido.

Entonces, escribimos una prueba y la enviamos a una rama específica en nuestro repositorio de prueba. Elegimos las pruebas que queremos ejecutar, elegimos una compilación para ejecutar, o tal vez una confirmación específica, en la que se ensamblará la compilación. Ahora ejecute la prueba, espere un momento y obtenga el resultado.





En este caso, se lanzaron 575 pruebas, de las cuales el 97% tuvieron éxito. Nos llevó unas tres horas completar todas las pruebas. A modo de comparación, las mismas pruebas, si se realizan manualmente, tomarían al menos 50 horas de operación continua.

Entonces, ¿qué pasó con el 3% de las pruebas que fallaron?

Abrimos una prueba específica y vemos un mensaje de que ocurrió un error al hacer coincidir las capturas de pantalla.



Luego abrimos la captura de pantalla, que en ese momento estaba en el dispositivo, y vemos que las zonas que no corresponden al original están marcadas con píxeles rojos. A modo de comparación, le damos.





Naturalmente, después de esto, el ingeniero de control de calidad debe corregir el error de que el comportamiento de la compilación no corresponde al documento de diseño del juego, o actualizar las capturas de pantalla originales, porque el documento de diseño del juego ha cambiado, y ahora estos elementos no estarán en el juego.


Se ve genial. ¿Por qué es todo esto necesario?


Hace algún tiempo, en el proyecto War Robots, necesitábamos hacer una pequeña refactorización. Consistió en reescribir algunas piezas de código para disparar armas, en particular, ametralladoras.

Durante las pruebas, encontramos un matiz interesante: la tasa de ametralladoras dependía directamente del FPS. Tal error no sería realista de detectar durante las pruebas manuales: en primer lugar, debido a las características del cálculo de daños de la red en el proyecto, y en segundo lugar, debido al hecho de que la aplicación War Robots está bastante bien optimizada y en ese momento se ejecutó dispositivos con aproximadamente el mismo FPS - 30 cuadros / s. Por supuesto, hubo pequeñas desviaciones, pero no fueron suficientes para notar un aumento en el daño por disparar armas durante las pruebas manuales. Luego nos preguntamos: ¿cuántos errores todavía tenemos y cuántos pueden aparecer durante la refactorización?

Como no queríamos reducir la cantidad de pruebas, sino aumentarla, ya que habíamos planeado actualizaciones importantes y un aumento en la cantidad de contenido, no queríamos crecer horizontalmente y aumentar la cantidad de empleados del departamento de control de calidad. En cambio, planeamos un crecimiento vertical con una reducción en la rutina de los empleados actuales y facilitando sus vidas durante las pruebas de integración de contenido nuevo.




¿Qué herramientas utilizamos?


Cuando comenzamos a automatizar las pruebas, en primer lugar, prestamos atención a las Herramientas de prueba de integración de Unity, que estaban integradas en ese momento en Unity. Escribimos varias IU y pruebas centrales en él, terminamos la refactorización que comenzamos antes y quedamos satisfechos con ella, porque la solución ya funcionó, lo que significa que nuestras suposiciones eran correctas, y tuvimos que seguir adelante. Lo único negativo de esta solución, pero muy significativo para nosotros, fue que las pruebas no podían ejecutarse en dispositivos móviles.

Por lo tanto, se nos ocurrió la idea de usar el marco de Appium. Esta es una bifurcación de otro marco de prueba conocido: Selenium. A su vez, es quizás el marco más famoso para probar aplicaciones web, cuyo concepto principal es trabajar con elementos de la interfaz de usuario, obtener sus coordenadas y organizar la entrada en estos elementos de la interfaz de usuario. Appium adoptó este concepto y, además de los controladores web existentes en Selenium, también agregó controladores iOS y Android: usan marcos de prueba nativos para cada una de estas plataformas.

Como no hay elementos de interfaz de usuario nativos en Unity, y solo hay un elemento de interfaz de usuario en el que se representa la imagen, tuve que agregar además del Appium UnityDriver, que le permite trabajar con la jerarquía de escenas, obtener objetos de escena y mucho más.

En ese momento, un ingeniero de control de calidad ya había aparecido en el proyecto, las cosas comenzaron a fluir, el número de escenarios de prueba comenzó a crecer significativamente, lo que gradualmente automatizamos. Comenzamos a lanzarlos en dispositivos y, en general, nuestro trabajo ya tenía el aspecto que queríamos.

En el futuro, además de las pruebas de IU, comenzaron a aparecer pruebas centrales y otras herramientas basadas en nuestro sistema, como resultado de lo cual nos encontramos con el rendimiento y la calidad del trabajo en varios dispositivos, agregamos soporte para varios dispositivos más, pruebas paralelas y también abandonamos Appium en beneficio de su propio marco.



El único problema que quedó con nosotros, y aún lo es, fue la jerarquía de la interfaz de usuario. Porque si una jerarquía cambia en una escena debido a la refactorización de la interfaz de usuario o al trabajo en la escena, esto debe ser compatible con las pruebas.

Después de las siguientes innovaciones y revisiones, la arquitectura de todo el sistema comenzó a verse de la siguiente manera.



Tomamos la compilación de War Robots, tomamos nuestras pruebas, que están en un repositorio separado, agregamos algunos parámetros para ejecutar allí que nos permiten configurar el lanzamiento de las pruebas en cada caso, y lo enviamos todo al agente TeamCity en una PC remota. El agente TeamCity lanza nuestras pruebas, les pasa los parámetros de compilación y lanzamiento de "Robots", después de lo cual las pruebas comienzan a funcionar y se "comunican" de forma independiente con los dispositivos que están conectados al agente TeamCity por cable: poner compilaciones en ellos, ejecutarlos, ejecutar ciertos scripts, eliminar compilaciones, reinicia la aplicación, etc.

Dado que las pruebas y la aplicación en sí se ejecutan en dispositivos físicamente diferentes, en un teléfono móvil y Mac mini, tuvimos que implementar la comunicación entre nuestro marco, War Robots API y Unity API. Hemos agregado un pequeño servidor UDP a la aplicación, que recibe comandos del marco y se comunica con la aplicación API y Unity a través de controladores.



La tarea principal de nuestro marco es organizar el trabajo de las pruebas: la preparación, finalización y gestión correcta de los dispositivos. En particular, la paralelización para acelerar el trabajo, la elección correcta de dispositivos y capturas de pantalla, la comunicación con la compilación. Después de completar las pruebas, nuestro marco debe guardar todos los artefactos generados y generar un informe.


Consejos para elegir dispositivos


Por separado, quiero prestar atención a la elección de los dispositivos para las pruebas.

Se debe prestar considerable atención a los centros. Si desea ejecutar puntos de referencia en sus dispositivos, especialmente si son dispositivos Android, se quedarán sin energía. Los concentradores deben proporcionar la potencia necesaria para los dispositivos utilizados. Hay otra característica muy sutil: algunos concentradores tienen energía activa, y esta energía se apaga después de sobretensiones, después de lo cual se enciende solo presionando físicamente un botón. Tenemos tales centros, y esto es muy inconveniente.

Si desea ejecutar pruebas de IU de regresión y lógica de prueba en dispositivos, no tome dispositivos diferentes. Tome los mismos dispositivos, mejor los más productivos que pueda pagar, porque de esta manera ahorrará tiempo en los frenos del dispositivo, la conveniencia de trabajar con ellos y el comportamiento de la aplicación en todos los dispositivos será el mismo.

Otro problema es el uso de granjas en la nube. Todavía no los usamos, aunque hemos realizado una investigación sobre ellos: cuáles son, cuánto cuestan y cómo realizar nuestras pruebas en ellos, pero hasta ahora tenemos suficiente de nuestro parque de dispositivos interno para cubrir nuestras solicitudes.


Informe de prueba


Una vez que se completan las pruebas, generamos un informe atractivo, que incluye todos los artefactos que se crearon durante nuestra prueba.

El principal "caballo de batalla" para analizar lo que sucedió e identificar las causas del accidente durante la prueba son los registros. En primer lugar, los recopilamos de nuestro marco, que nos informa sobre el estado del guión y lo que sucedió en este guión. Dividimos los registros en el sistema (más detallado) y el registro de QA (más compacto y conveniente para el análisis). También recopilamos registros del sistema de dispositivos (por ejemplo, logcat) y registros de una aplicación de Unity.

Durante la caída de las pruebas, también tomamos una captura de pantalla para comprender lo que estaba sucediendo en los dispositivos en el momento de la caída, grabar un video para comprender lo que sucedió antes del accidente e intentar recopilar la máxima información sobre el estado del dispositivo, como los pings de nuestros servidores e información en ifconfig para entender si el dispositivo tiene una IP. Sin embargo, se sorprenderá si inicia la aplicación manualmente 50 veces, todo estará bien con ella, pero si la ejecuta 50 mil veces en modo automático, encontrará que Internet en el dispositivo puede perderse, y no estará claro durante la prueba, si hubo una conexión antes y después de la caída.

También recopilamos una lista de procesos, energía de la batería, temperatura y, en general, todo lo que podemos alcanzar.




¿Cuáles son buenas capturas de pantalla y videos?


Hace algún tiempo, nuestro ingeniero de control de calidad sugirió, además de tomar capturas de pantalla en otoño, en ciertos lugares de las pruebas para comparar estas capturas de pantalla con las plantillas que se encuentran en nuestro repositorio. Por lo tanto, propuso ahorrar tiempo en la cantidad de ejecuciones de prueba y reducir el tamaño de la base del código. Es decir, con una prueba podríamos verificar la lógica y la parte visual. Desde el punto de vista del concepto de prueba unitaria, esto no es muy correcto, porque en una prueba no deberíamos probar varias hipótesis. Pero este es un paso deliberado: sabemos cómo analizar todo esto correctamente, por lo que nos aventuramos a agregar una funcionalidad similar.

En primer lugar, pensamos en agregar bibliotecas para que coincidan con las capturas de pantalla, pero nos dimos cuenta de que usar imágenes con diferentes resoluciones no es muy confiable, por lo que nos detuvimos en dispositivos con la misma resolución y simplemente comparamos las imágenes con un cierto umbral píxel por píxel.



Un efecto muy interesante del uso de la coincidencia de capturas de pantalla es que si algún proceso es difícil de automatizar, lo automatizaremos hasta donde resulta, y luego simplemente miramos las capturas de pantalla manualmente. Esto es exactamente lo que hicimos con la localización de prueba. Recibimos una solicitud para probar la localización de nuestras aplicaciones, por lo que comenzamos a buscar bibliotecas que permitieran el reconocimiento de texto, pero nos dimos cuenta de que era poco confiable y, como resultado, escribimos varios scripts que "recorren" diferentes pantallas y causan diferentes ventanas emergentes. ups, y en este momento se crean capturas de pantalla. Antes de comenzar tal script, cambiamos la configuración regional en el dispositivo, ejecutamos la secuencia de comandos, tomamos capturas de pantalla, cambiamos la configuración regional nuevamente y ejecutamos la secuencia de comandos nuevamente. Por lo tanto, todas las pruebas se realizan de noche,para que por la mañana el ingeniero de control de calidad pueda ver 500 capturas de pantalla y analizar de inmediato si hay problemas con la localización en alguna parte. Sí, las capturas de pantalla aún deben ser vistas, pero esto es mucho más rápido que pasar manualmente por todas las pantallas del dispositivo.

A veces, las capturas de pantalla y los registros no son suficientes: algo extraño comienza a suceder en los dispositivos, pero como están ubicados de forma remota, no puede ir y evaluar lo que sucedió allí. Además, a veces no está claro qué sucedió literalmente unos momentos antes de que cayera la prueba. Por lo tanto, agregamos una grabación de video desde el dispositivo, que comienza con el inicio de la prueba y se guarda solo en caso de una caída. Con la ayuda de tales videos, es muy conveniente rastrear bloqueos y bloqueos de aplicaciones.




¿Qué más puede hacer nuestro sistema?


Hace algún tiempo, del departamento de pruebas de control de calidad, recibimos una solicitud para desarrollar una herramienta para recopilar métricas durante las pruebas de juego manuales.

¿Para qué sirve?

Esto es necesario para que los ingenieros de control de calidad, después de una prueba de reproducción manual, puedan analizar adicionalmente el comportamiento de FPS y el consumo de memoria en la aplicación, mirando simultáneamente capturas de pantalla y videos que reflejen lo que estaba sucediendo en este dispositivo.

El sistema desarrollado por nosotros funcionó de la siguiente manera. El ingeniero de control de calidad lanzó War Robots en el dispositivo, activó el registro de la sesión de playbench, nuestro análogo del gamebench, jugó la prueba de juego, luego hizo clic en "finalizar la sesión de playbench", el informe generado se guardó en el repositorio, después de lo cual el ingeniero con los datos para esta prueba de prueba pudo llegar a su trabajo máquinas y ver el informe: cuáles fueron los inconvenientes en FPS, qué consumo de memoria, qué estaba sucediendo en el dispositivo.

También automatizamos el lanzamiento de puntos de referencia en el proyecto War Robots, esencialmente simplemente envolviendo los puntos de referencia existentes en un lanzamiento automático. El resultado de los puntos de referencia suele ser un dígito. En nuestro caso, este suele ser el FPS promedio por punto de referencia. Además del lanzamiento automático, decidimos agregar otra sesión de playbench y, por lo tanto, recibimos no solo una figura específica, cómo funcionaba el punto de referencia, sino también información gracias a la cual podemos analizar lo que sucedió con el punto de referencia en ese momento.

También debemos mencionar la prueba de solicitud de extracción. Esta vez fue más para ayudar al equipo de desarrollo del cliente, en lugar de los ingenieros de control de calidad. Ejecutamos la llamada prueba de verificación de compilación para cada solicitud de extracción. Puede ejecutarlos tanto en dispositivos como en el editor de Unity para acelerar el trabajo de verificación de la lógica. También ejecutamos un conjunto de pruebas centrales en ramas separadas, donde se lleva a cabo una especie de rediseño de algunos elementos o refactorización de código.




Y otras características útiles.


Al final, quiero hacer hincapié en algunos casos interesantes que hemos conocido en los últimos años.

Uno de los casos más interesantes que apareció recientemente con nosotros son los puntos de referencia durante las peleas con bots.

Para el nuevo proyecto, Pixonic Dino Squad desarrolló un sistema en el que el ingeniero de control de calidad podía jugar una prueba de juego con bots, para no esperar a sus colegas, sino para probar algunas hipótesis. Nuestro ingeniero de control de calidad, a su vez, pidió agregar la capacidad no solo de jugar con bots, sino también para que los bots puedan jugar entre ellos. Por lo tanto, simplemente iniciamos la aplicación, y en este momento el bot comienza a jugar con otros bots. Al mismo tiempo, toda la interacción es en red, con servidores reales, en lugar de jugadores que juegan una computadora. Todo esto está envuelto en puntos de referencia y una sesión de playbench con disparadores para comenzar de noche. Por lo tanto, en la noche comenzamos varias batallas entre bots y bots, en este momento se escriben FPS y consumo de memoria, se toman capturas de pantalla y se graban videos. Por la mañana, el ingeniero de control de calidad viene y puede ver,qué pruebas de juego se llevaron a cabo y qué pasó con ellas.

También vale la pena comprobar si hay fugas de textura. Este es un tipo de subanálisis del uso de memoria, pero aquí verificamos principalmente el uso, por ejemplo, de texturas de garaje en la batalla. En consecuencia, en la batalla no debería haber atlas que se usan en el garaje, y cuando salimos de la batalla, las texturas que se usaron en la batalla no deberían permanecer en la memoria.

Un efecto secundario interesante de nuestro sistema es que casi desde el comienzo de su uso, rastreamos el tiempo de carga de la aplicación. En el caso de War Robots, esta vez no es fuerte, pero está en constante crecimiento, porque se está agregando nuevo contenido y la calidad de este contenido está mejorando, pero podemos mantener este parámetro bajo control y estar siempre conscientes de su tamaño.


En lugar de una conclusión


Al final, me gustaría llamar la atención sobre los problemas que tenemos que conocemos y que nos gustaría resolver en primer lugar.



El primero y más doloroso son los cambios en la IU. Dado que trabajamos con la caja negra, no incorporamos nada en la aplicación War Robots, excepto nuestro servidor, es decir, probamos todo de la misma manera que lo haría un ingeniero de control de calidad. Pero de alguna manera necesitamos acceder a los elementos de la escena. Y los encontramos a lo largo del camino absoluto. Por lo tanto, cuando algo cambia en el escenario, especialmente en un alto nivel de jerarquía, tenemos que apoyar estos cambios en una gran cantidad de pruebas. Desafortunadamente, no podemos hacer nada al respecto en este momento. Por supuesto, hay algunas soluciones, pero traen sus problemas adicionales.

El segundo gran problema es la infraestructura. Como dije, si ejecuta su aplicación 50 veces con sus manos, no notará la mayoría de los problemas que saldrán a la luz si ejecuta su aplicación 50 mil veces. Esos problemas que pueden resolverse fácilmente en modo manual, por ejemplo, reinstalar compilaciones o reiniciar Internet, resultarán ser una verdadera molestia en la automatización, porque todos estos problemas deben manejarse correctamente, aparecer un mensaje de error y siempre que puedan ocurrir. En particular, tenemos que determinar por qué cayeron las pruebas: debido a un mal funcionamiento de la lógica o algún tipo de problema de infraestructura, o por cualquier otra razón. Hay muchos problemas con los dispositivos de gama baja: no tienen compilaciones, Internet se cae, los dispositivos se congelan, se bloquean, no se encienden, se descargan rápidamente, etc.

También me gustaría interactuar con interfaces de usuario nativas, pero hasta ahora no tenemos esa oportunidad. Sabemos cómo hacer esto, pero la presencia de otras solicitudes de funcionalidad no nos permite llegar a esto.

Y personalmente, mi deseo es cumplir con los estándares que existen en la industria, pero esto también está en los planes para el futuro, tal vez incluso este año.

All Articles