Monolito para cientos de versiones de clientes: c贸mo escribimos y respaldamos las pruebas



Hola a todos!

Soy un desarrollador de backend en el equipo del servidor Badoo. En la conferencia HighLoad del a帽o pasado, hice una presentaci贸n , una versi贸n de texto que quiero compartir con ustedes. Esta publicaci贸n ser谩 m谩s 煤til para aquellos que escriben pruebas para el backend y experimentan problemas con las pruebas de c贸digo heredado, as铆 como para aquellos que desean probar la l贸gica empresarial compleja.

驴De qu茅 hablaremos? Primero, hablar茅 brevemente sobre nuestro proceso de desarrollo y c贸mo afecta nuestra necesidad de pruebas y el deseo de escribir estas pruebas. Luego, subiremos y bajaremos la pir谩mide de automatizaci贸n de pruebas, discutiremos los tipos de pruebas que usamos, hablaremos sobre las herramientas dentro de cada una de ellas y qu茅 problemas resolvemos con su ayuda. Al final, considere c贸mo mantener y ejecutar todo esto.

Nuestro proceso de desarrollo


Hemos ilustrado nuestro proceso de desarrollo:


Un golfista es un desarrollador de backend. En alg煤n momento, una tarea de desarrollo se traslada a 茅l, generalmente en forma de dos documentos: requisitos del lado comercial y un documento t茅cnico que describe los cambios en nuestro protocolo de interacci贸n entre el servidor y los clientes (aplicaciones m贸viles y el sitio).

El desarrollador escribe el c贸digo y lo pone en funcionamiento, y antes que todas las aplicaciones cliente. Toda la funcionalidad est谩 protegida por algunos indicadores de caracter铆sticas o pruebas A / B, esto se prescribe en un documento t茅cnico. Despu茅s de eso, de acuerdo con las prioridades actuales y la hoja de ruta del producto, se lanzan las aplicaciones del cliente. Para nosotros, los desarrolladores de back-end, es completamente impredecible cu谩ndo se implementar谩 una caracter铆stica particular en los clientes. El ciclo de lanzamiento para las aplicaciones del cliente es algo m谩s complicado y m谩s largo que el nuestro, por lo que nuestros gerentes de producto literalmente hacen malabares con las prioridades.

La cultura de desarrollo adoptada por la compa帽铆a es de gran importancia: el desarrollador de back-end es responsable de la caracter铆stica desde el momento de su implementaci贸n en el back-end hasta la 煤ltima integraci贸n en la 煤ltima plataforma en la que originalmente se plane贸 implementar esta caracter铆stica.

Esta situaci贸n es bastante posible: hace seis meses, implement贸 alguna caracter铆stica, los equipos de clientes no la implementaron durante mucho tiempo, porque las prioridades de la empresa han cambiado, ya est谩 ocupado trabajando en otras tareas, tiene nuevos plazos, prioridades, y aqu铆 vienen sus colegas y dicen: "驴Recuerdas esto que te lavaste hace seis meses? Ella no est谩 trabajando ". Y en lugar de involucrarse en nuevas tareas, apaga los incendios.



Por lo tanto, nuestros desarrolladores tienen una motivaci贸n inusual para los programadores de PHP: asegurarse de que haya la menor cantidad de problemas posible durante la fase de integraci贸n.

驴Qu茅 quiere hacer en primer lugar para asegurarse de que la funci贸n funcione?

Por supuesto, lo primero que viene a la mente es realizar pruebas manuales. Recoge la aplicaci贸n, pero no sabe c贸mo: debido a que la funci贸n es nueva, los clientes se ocupar谩n de ella en seis meses. Bueno, las pruebas manuales no garantizan que, durante el tiempo que transcurrir谩 desde el lanzamiento del backend hasta el inicio de la integraci贸n, nadie romper谩 nada con los clientes.

Y aqu铆 las pruebas automatizadas vienen en nuestra ayuda.

Pruebas unitarias


Las pruebas m谩s simples que escribimos son pruebas unitarias. Usamos PHP como lenguaje principal para el backend, y PHPUnit como marco para pruebas unitarias. Mirando hacia el futuro, dir茅 que todas nuestras pruebas de back-end est谩n escritas sobre la base de este marco.

Las pruebas unitarias a menudo cubrimos algunos peque帽os fragmentos de c贸digo aislados, verificamos el rendimiento de m茅todos o funciones, es decir, estamos hablando de peque帽as unidades de l贸gica de negocios. Nuestras pruebas unitarias no deben interactuar con nada, acceder a bases de datos o servicios.

Softmocks


La principal dificultad que enfrentan los desarrolladores al escribir pruebas unitarias es el c贸digo no comprobable, y este suele ser el c贸digo heredado.

Un simple ejemplo. Badoo tiene 12 a帽os, una vez fue una startup muy peque帽a, que fue desarrollada por varias personas. El inicio existi贸 con bastante 茅xito sin ninguna prueba en absoluto. Luego nos volvimos lo suficientemente grandes y nos dimos cuenta de que no puedes vivir sin pruebas. Pero para entonces se hab铆a escrito mucho c贸digo que funcionaba. 隆No lo reescribas solo por probar! Eso no ser铆a muy razonable desde el punto de vista comercial.

Por lo tanto, desarrollamos una peque帽a biblioteca de c贸digo abierto SoftMocks , que hace que nuestro proceso de escritura de pruebas sea m谩s barato y m谩s r谩pido. Intercepta todos los archivos PHP de incluir / requerir y sobre la marcha reemplaza el archivo fuente con contenido modificado, es decir, c贸digo reescrito. Esto nos permite crear talones para cualquier c贸digo. Detalla c贸mo funciona la biblioteca.

Esto es lo que parece para un desarrollador:

//mock  \Badoo\SoftMocks::redefineConstant($constantName, $newValue); //mock  : , ,  \Badoo\SoftMocks::redefineMethod( $class, $method, $method_args, $fake_code ); //mock  \Badoo\SoftMocks::redefineFunction( $function, $function_args, $fake_code ); 

Con la ayuda de construcciones tan simples, podemos redefinir globalmente todo lo que queramos. En particular, nos permiten sortear las limitaciones del creador est谩ndar de PHPUnit. Es decir, podemos burlarnos de m茅todos est谩ticos y privados, redefinir constantes y hacer mucho m谩s, lo cual es imposible en PHPUnit ordinario.

Sin embargo, nos encontramos con un problema: a los desarrolladores les parece que si hay SoftMocks, no hay necesidad de escribir el c贸digo probado; siempre se puede "peinar" el c贸digo con nuestros simulacros globales, y todo funcionar谩 bien. Pero este enfoque conduce a un c贸digo m谩s complejo y a la acumulaci贸n de "muletas". Por lo tanto, adoptamos varias reglas que nos permiten mantener la situaci贸n bajo control:

  1. Todo el c贸digo nuevo debe probarse f谩cilmente con simulacros est谩ndar de PHPUnit. Si se cumple esta condici贸n, entonces el c贸digo es comprobable y puede seleccionar f谩cilmente una pieza peque帽a y probarla solo.
  2. SoftMocks se puede usar con c贸digo antiguo que est谩 escrito de una manera que no es adecuada para pruebas unitarias, as铆 como en casos donde es demasiado costoso / largo / dif铆cil de hacer de otra manera (enfatice lo necesario).

El cumplimiento de estas reglas se supervisa cuidadosamente en la etapa de revisi贸n del c贸digo.

Prueba de mutaci贸n


Por separado, quiero decir sobre la calidad de las pruebas unitarias. Creo que muchos de ustedes usan m茅tricas como la cobertura de c贸digo. Pero ella, desafortunadamente, no responde una pregunta: "驴He escrito una buena prueba de unidad?" Es posible que haya escrito una prueba de este tipo, que en realidad no verifica nada, no contiene una sola afirmaci贸n, pero genera una excelente cobertura de c贸digo. Por supuesto, el ejemplo es exagerado, pero la situaci贸n no est谩 tan lejos de la realidad.

Recientemente, comenzamos a introducir pruebas mutacionales. Este es un concepto bastante antiguo, pero no muy conocido. El algoritmo para tales pruebas es bastante simple:

  • tomar el c贸digo y la cobertura del c贸digo;
  • parsim y comenzar a cambiar el c贸digo: verdadero a falso,> a> =, + a - (en general, da帽o en todos los sentidos);
  • para cada cambio de mutaci贸n, ejecute conjuntos de pruebas que cubran la cadena modificada;
  • si las pruebas caen, entonces son buenas y realmente no nos permiten romper el c贸digo;
  • si las pruebas han pasado, lo m谩s probable es que no sean lo suficientemente efectivas, a pesar de la cobertura, y puede valer la pena mirarlas m谩s de cerca, para afirmar algo (o hay un 谩rea no cubierta por la prueba).

Hay varios frameworks listos para PHP, como Humbug e Infection. Desafortunadamente, no nos conven铆an, porque son incompatibles con SoftMocks. Por lo tanto, escribimos nuestra propia peque帽a consola, que hace lo mismo, pero usa nuestro formato de cobertura de c贸digo interno y es amigo de SoftMocks. Ahora el desarrollador lo inicia manualmente y analiza las pruebas escritas por 茅l, pero estamos trabajando para introducir la herramienta en nuestro proceso de desarrollo.

Pruebas de integraci贸n


Con la ayuda de pruebas de integraci贸n, verificamos la interacci贸n con varios servicios y bases de datos.

Para comprender mejor la historia, desarrollemos una promoci贸n ficticia y c煤brala con pruebas. Imagine que nuestros gerentes de producto decidieron distribuir boletos de conferencia a nuestros usuarios m谩s dedicados:


La promoci贸n debe mostrarse si:

  • el usuario en el campo "Trabajo" indica "programador",
  • el usuario participa en la prueba A / B HL18_promo,
  • El usuario est谩 registrado hace m谩s de dos a帽os.

Al hacer clic en el bot贸n "Obtener un boleto", debemos guardar los datos de este usuario en una lista para transferirlos a nuestros gerentes que distribuyen los boletos.

Incluso en este ejemplo bastante simple, hay algo que no se puede verificar mediante pruebas unitarias: la interacci贸n con la base de datos. Para hacer esto, necesitamos usar pruebas de integraci贸n.

Considere la forma est谩ndar de probar la interacci贸n de la base de datos ofrecida por PHPUnit:

  1. Eleve la base de datos de prueba.
  2. Preparamos DataTables y DataSets.
  3. Ejecute la prueba
  4. Limpiamos la base de datos de prueba.

驴Qu茅 dificultades acechan con este enfoque?

  • Debe admitir las estructuras de DataTables y DataSets. Si cambiamos el dise帽o de la tabla, entonces es necesario reflejar estos cambios en la prueba, lo que no siempre es conveniente y requiere tiempo adicional.
  • Lleva tiempo preparar la base de datos. Cada vez que configuramos la prueba, necesitamos cargar algo all铆, crear algunas tablas, y esto es largo y problem谩tico si hay muchas pruebas.
  • Y el inconveniente m谩s importante: ejecutar estas pruebas en paralelo las hace inestables. Comenzamos la prueba A, 茅l comenz贸 a escribir en la tabla de prueba, que 茅l cre贸. Al mismo tiempo, lanzamos la prueba B, que quiere trabajar con la misma tabla de prueba. Como resultado, surgen bloqueos mutuos y otras situaciones imprevistas.

Para evitar estos problemas, desarrollamos nuestra propia biblioteca peque帽a DBMocks.

DBMocks


El principio de funcionamiento es el siguiente:

  1. Con la ayuda de SoftMocks, interceptamos todos los contenedores a trav茅s de los cuales trabajamos con bases de datos.
  2. Cuando
    la consulta pasa por simulacro, analiza la consulta SQL y extrae DB + TableName de ella, y obtiene el host de la conexi贸n.
  3. En el mismo host en tmpfs creamos una tabla temporal con la misma estructura que la original (copiamos la estructura usando SHOW CREATE TABLE).
  4. Despu茅s de eso, redirigiremos todas las solicitudes que pasar谩n por simulacro a esta tabla a una temporal reci茅n creada.

驴Qu茅 nos da esto?

  • no es necesario cuidar constantemente las estructuras;
  • las pruebas ya no pueden da帽ar los datos en las tablas de origen, porque los redirigimos a tablas temporales sobre la marcha;
  • todav铆a estamos probando la compatibilidad con la versi贸n de MySQL con la que estamos trabajando, y si la solicitud deja de ser compatible con la nueva versi贸n, nuestra prueba lo ver谩 y la bloquear谩.
  • y lo m谩s importante, las pruebas ahora est谩n aisladas, e incluso si las ejecuta en paralelo, los subprocesos se dispersar谩n en diferentes tablas temporales, ya que agregamos una clave 煤nica para cada prueba en los nombres de las tablas de prueba.

Pruebas de API


La diferencia entre las pruebas unitarias y API est谩 bien ilustrada en este GIF:


La cerradura funciona bien, pero est谩 unida a la puerta equivocada.

Nuestras pruebas simulan una sesi贸n de cliente, pueden enviar solicitudes al backend, siguiendo nuestro protocolo, y el backend responde a ellas como un cliente real.

Probar grupo de usuarios


驴Qu茅 necesitamos para escribir con 茅xito tales pruebas? Volvamos a las condiciones del espect谩culo de nuestra promoci贸n:

  • el usuario en el campo "Trabajo" indica "programador",
  • el usuario participa en la prueba A / B HL18_promo,
  • El usuario est谩 registrado hace m谩s de dos a帽os.

Aparentemente, aqu铆 todo se trata del usuario. Y en realidad, el 99% de las pruebas de API requieren un usuario registrado autorizado, que est谩 presente en todos los servicios y bases de datos.

驴D贸nde conseguirlo? Puede intentar registrarlo en el momento de la prueba, pero:

  • es largo y consume muchos recursos;
  • despu茅s de completar la prueba, este usuario debe ser eliminado de alguna manera, lo cual es una tarea bastante trivial si hablamos de proyectos grandes;
  • finalmente, como en muchos otros proyectos altamente cargados, realizamos muchas operaciones en segundo plano (agregando un usuario a varios servicios, replicaci贸n a otros centros de datos, etc.); Las pruebas no saben nada sobre tales procesos, pero si se basan impl铆citamente en los resultados de su ejecuci贸n, existe el riesgo de inestabilidad.


Desarrollamos una herramienta llamada Test Users Pool. Se basa en dos ideas:

  1. No registramos usuarios cada vez, pero lo usamos muchas veces.
  2. Despu茅s de la prueba, restablecemos los datos del usuario a su estado original (en el momento del registro). Si no se hace esto, las pruebas se volver谩n inestables con el tiempo, porque los usuarios estar谩n "contaminados" con la informaci贸n de otras pruebas.


Funciona algo como esto:



En alg煤n momento, quer铆amos ejecutar nuestras pruebas de API en un entorno de producci贸n. 驴Por qu茅 queremos esto? Porque la infraestructura de desarrollo no es lo mismo que la producci贸n.

Aunque estamos tratando de repetir constantemente la infraestructura de producci贸n en un tama帽o reducido, el desarrollo nunca ser谩 una copia completa de la misma. Para estar absolutamente seguro de que la nueva compilaci贸n cumple con las expectativas y no hay problemas, cargamos el nuevo c贸digo en el cl煤ster de preproducci贸n, que funciona con datos y servicios de producci贸n, y ejecutamos nuestras pruebas de API all铆.

En este caso, es muy importante pensar en c贸mo aislar a los usuarios de prueba de los reales.

Qu茅 suceder谩 si los usuarios de prueba comienzan a aparecer reales en nuestra aplicaci贸n.


驴C贸mo aislar? Cada uno de nuestros usuarios tiene una bandera is_test_user . En la etapa de registro, se convierte en yes o no , y ya no cambia. Con esta bandera, aislamos a los usuarios en todos los servicios. Tambi茅n es importante que excluyamos a los usuarios de prueba del an谩lisis empresarial y los resultados de las pruebas A / B para no distorsionar las estad铆sticas.

Puede ir de una manera m谩s simple: comenzamos con el hecho de que todos los usuarios de prueba fueron "reubicados" en la Ant谩rtida. Si tiene un geoservicio, esta es una forma completamente funcional.

API de control de calidad


No solo necesitamos un usuario, lo necesitamos con ciertos par谩metros: para trabajar como programador, participar en una determinada prueba A / B y fue registrado hace m谩s de dos a帽os. Para los usuarios de prueba, podemos asignar f谩cilmente una profesi贸n usando nuestra API de back-end, pero entrar en las pruebas A / B es probabil铆stico. Y la condici贸n de registro hace m谩s de dos a帽os es generalmente dif铆cil de cumplir, porque no sabemos cu谩ndo apareci贸 el usuario en el grupo.

Para resolver estos problemas, tenemos una API de control de calidad. Esto, de hecho, es una puerta trasera para las pruebas, que es un m茅todo API bien documentado que le permite administrar r谩pida y f谩cilmente los datos del usuario y cambiar su estado sin pasar por el protocolo principal de nuestra comunicaci贸n con los clientes. Los desarrolladores de backend escriben los m茅todos para ingenieros de control de calidad y para su uso en pruebas de interfaz de usuario y API.

QA API solo se puede aplicar en el caso de usuarios de prueba: si no hay un indicador correspondiente, la prueba caer谩 inmediatamente. Este es uno de nuestros m茅todos de API de control de calidad que le permite cambiar la fecha de registro del usuario a una arbitraria:



Por lo tanto, se ver谩n como tres llamadas que le permitir谩n cambiar r谩pidamente los datos del usuario de prueba para que cumplan las condiciones para mostrar la promoci贸n:

  • En el campo "Trabajo" se indica el "programador":
    addUserWorkEducation?user_id=ID&works[]=Badoo,

  • El usuario participa en la prueba A / B HL18_promo:
    forceSplitTest?user_id=ID&test=HL18_promo
  • Registrado hace m谩s de dos a帽os:
    userCreatedChange?user_id=ID&created=2016-09-01


Como se trata de una puerta trasera, es imperativo pensar en la seguridad. Protegimos nuestro servicio de varias maneras:

  • aislado a nivel de red: solo se puede acceder a los servicios desde la red de la oficina;
  • con cada solicitud pasamos un secreto, sin el cual es imposible acceder a la API de QA incluso desde la red de la oficina;
  • Los m茅todos solo funcionan con usuarios de prueba.


Remotemocks


Para trabajar con el back-end remoto de las pruebas API, es posible que necesitemos simulacros. Para que? Por ejemplo, si la prueba de API en el entorno de producci贸n comienza a acceder a la base de datos, debemos asegurarnos de que los datos en ella se borren de los datos de prueba. Adem谩s, los simulacros ayudan a que la respuesta de la prueba sea m谩s adecuada para la prueba.

Tenemos tres textos:



Badoo es una aplicaci贸n multiling眉e, tenemos un componente complejo de localizaci贸n que le permite traducir y recibir traducciones r谩pidamente para la ubicaci贸n actual del usuario. Nuestros localizadores trabajan constantemente para mejorar las traducciones, realizar pruebas A / B con tokens y buscar formulaciones m谩s exitosas. Y, mientras realizamos la prueba, no podemos saber qu茅 texto devolver谩 el servidor; puede cambiar en cualquier momento. Pero podemos usar RemoteMocks para verificar si se accede correctamente al componente de localizaci贸n.

驴C贸mo funcionan los RemoteMocks? La prueba le pide al servidor que los inicialice para su sesi贸n, y al recibir todas las solicitudes posteriores, el servidor comprueba si hay simulacros para la sesi贸n actual. Si lo son, simplemente los inicializa usando SoftMocks.

Si queremos crear una simulaci贸n remota, indicamos qu茅 clase o m茅todo necesita ser reemplazado y con qu茅. Todas las solicitudes de backend posteriores se ejecutar谩n teniendo en cuenta este simulacro:

 $this->remoteInterceptMethod( \Promo\HighLoadConference::class, 'saveUserEmailToDb', true ); 

Bueno, ahora recopilemos nuestra prueba de API:

 //       $app_startup = [ 'supported_promo_blocks' => [\Mobile\Proto\Enum\PromoBlockType::GENERIC_PROMO] ]; $Client = $this->getLoginedConnection(BmaFunctionalConfig::USER_TYPE_NEW, $app_startup); //  $Client->getQaApiClient()->addUserWorkEducation(['Badoo, ']); $Client->getQaApiClient()->forceSplitTest('HL18_promo'); $Client->getQaApiClient()->userCreatedChange('2016-09-01'); //     $this->remoteInterceptMethod(\Promo\HighLoadConference::class, 'saveUserEmail', true); //,   ,   $Resp = $Client->ServerGetPromoBlocks([]); $this->assertTrue($Resp->hasMessageType('CLIENT_NEXT_PROMO_BLOCKS')); $PromoBlock = $Resp->CLIENT_NEXT_PROMO_BLOCKS; 鈥 //   CTA, ,   ,   $Resp = $Client->ServerPromoAccepted($PromoBlock->getPromoId()); $this->assertTrue($Resp->hasMessageType('CLIENT_ACKNOWLEDGE_COMMAND')); 


De una manera tan simple, podemos probar cualquier funcionalidad que se desarrolle en el backend y requiera cambios en el protocolo m贸vil.

Reglas de uso de prueba de API


Todo parece estar bien, pero nuevamente encontramos un problema: las pruebas de API resultaron ser demasiado convenientes para el desarrollo y hubo la tentaci贸n de usarlas en todas partes. Como resultado, una vez que nos dimos cuenta de que est谩bamos empezando a resolver problemas con la ayuda de las pruebas API para las cuales no estaban destinados.

驴Por qu茅 es esto malo? Porque las pruebas de API son muy lentas. Se conectan a la red, se dirigen al backend, que recoge la sesi贸n, va a la base de datos y a un conjunto de servicios. Por lo tanto, desarrollamos un conjunto de reglas para usar pruebas API:
  • El prop贸sito de las pruebas de API es verificar el protocolo de interacci贸n entre el cliente y el servidor, as铆 como la correcta integraci贸n del nuevo c贸digo;

  • est谩 permitido cubrir procesos complejos con ellos, por ejemplo, cadenas de acciones;
  • no pueden usarse para probar la peque帽a variabilidad de la respuesta del servidor; esta es la tarea de las pruebas unitarias;
  • durante la revisi贸n del c贸digo, verificamos las pruebas incluidas.

Pruebas de IU


Como estamos considerando una pir谩mide de automatizaci贸n, te contar茅 un poco sobre las pruebas de IU.

Los desarrolladores de backend en Badoo no escriben pruebas de interfaz de usuario; para esto tenemos un equipo dedicado en el departamento de control de calidad. Cubrimos la funci贸n con las pruebas de IU cuando ya se nos viene a la mente y se estabiliza, porque creemos que no es razonable gastar recursos en una automatizaci贸n bastante costosa de la funci贸n, que, tal vez, no vaya m谩s all谩 de la prueba A / B.

Utilizamos Calabash para pruebas autom谩ticas m贸viles y Selenium para la web. Habla sobre nuestra plataforma de automatizaci贸n y pruebas.

Prueba de funcionamiento


Ahora tenemos 100,000 pruebas unitarias, 6,000 - pruebas de integraci贸n y 14,000 pruebas API. Si intenta ejecutarlos en un hilo, incluso en nuestra m谩quina m谩s poderosa, una ejecuci贸n completa de todos tomar谩: modular - 40 minutos, integraci贸n - 90 minutos, pruebas API - diez horas. Es muy largo

Paralelizaci贸n


Hablamos sobre nuestra experiencia de paralelizar pruebas unitarias en este art铆culo .

La primera soluci贸n, que parece obvia, es ejecutar pruebas en m煤ltiples hilos. Pero fuimos m谩s all谩 e hicimos una nube para el lanzamiento paralelo para poder escalar los recursos de hardware. Simplificado, su trabajo se ve as铆:



La tarea m谩s interesante aqu铆 es la distribuci贸n de pruebas entre hilos, es decir, su desglose en trozos.

Puede dividirlos por igual, pero las pruebas son diferentes, por lo que puede haber un fuerte sesgo en el tiempo de ejecuci贸n de un hilo: todos los hilos ya han llegado y uno se cuelga durante media hora, ya que fue "afortunado" con pruebas muy lentas.

Puede iniciar varios subprocesos y alimentarlos con pruebas de uno en uno. En este caso, el inconveniente es menos obvio: existen costos generales para inicializar el entorno, que, con una gran cantidad de pruebas y este enfoque, comienzan a desempe帽ar un papel importante.

Que hemos hecho Comenzamos a recopilar estad铆sticas sobre el tiempo necesario para ejecutar cada prueba, y luego comenzamos a componer fragmentos de tal manera que, seg煤n las estad铆sticas, un subproceso se ejecute por no m谩s de 30 segundos. Al mismo tiempo, empaquetamos las pruebas bastante bien en trozos para hacerlas m谩s peque帽as.

Sin embargo, nuestro enfoque tambi茅n tiene un inconveniente. Est谩 asociado con las pruebas de API: son muy lentas y consumen muchos recursos, evitando que se ejecuten pruebas r谩pidas.

Por lo tanto, dividimos la nube en dos partes: en la primera, solo se lanzan pruebas r谩pidas, y en la segunda, se pueden iniciar tanto r谩pido como lento. Con este enfoque, siempre tenemos una parte de la nube que puede manejar pruebas r谩pidas.



Como resultado, las pruebas unitarias comenzaron a ejecutarse en un minuto, las pruebas de integraci贸n en cinco minutos y las pruebas de API en 15 minutos. Es decir, una carrera completa en lugar de 12 horas no lleva m谩s de 22 minutos.

Ejecuci贸n de prueba de cobertura de c贸digo


Tenemos un gran monolito complejo y, en el buen sentido, necesitamos ejecutar constantemente todas las pruebas, ya que un cambio en un lugar puede romper algo en otro. Esta es una de las principales desventajas de la arquitectura monol铆tica.

En alg煤n momento, llegamos a la conclusi贸n de que no es necesario ejecutar todas las pruebas cada vez; puede realizar ejecuciones basadas en la cobertura del c贸digo:

  1. Toma nuestra rama diff.
  2. Creamos una lista de archivos modificados.
  3. Para cada archivo obtenemos una lista de pruebas,
    que lo cubren
  4. A partir de estas pruebas, creamos un conjunto y lo ejecutamos en una nube de prueba.

驴D贸nde obtener cobertura? Recopilamos datos una vez al d铆a cuando la infraestructura del entorno de desarrollo est谩 inactiva. El n煤mero de pruebas ejecutadas ha disminuido notablemente, la velocidad de recibir comentarios de ellos, por el contrario, ha aumentado significativamente. Beneficio!

Una ventaja adicional fue la capacidad de ejecutar pruebas para parches. A pesar del hecho de que Badoo no ha sido una startup durante mucho tiempo, a煤n podemos implementar r谩pidamente cambios en la producci贸n, verter soluciones r谩pidas, implementar caracter铆sticas y cambiar la configuraci贸n. Como regla general, la velocidad de implementaci贸n de parches es muy importante para nosotros.El nuevo enfoque dio un gran aumento en la velocidad de retroalimentaci贸n de las pruebas, porque ahora no necesitamos esperar mucho para una ejecuci贸n completa.

Pero sin los defectos en ninguna parte. Lanzaremos el back-end dos veces al d铆a, y la cobertura es relevante solo para la primera versi贸n, hasta la primera compilaci贸n, despu茅s de lo cual comienza a retrasarse una compilaci贸n. Por lo tanto, para las compilaciones, ejecutamos un conjunto de pruebas completo. Para nosotros, esto es una garant铆a de que la cobertura del c贸digo no se queda atr谩s y que se han completado todas las pruebas necesarias. Lo peor que puede suceder es que atraparemos algunas pruebas fallidas en la etapa de construcci贸n de la construcci贸n, y no en las etapas anteriores. Pero esto sucede muy raramente.

API-, code coverage. , , . - , API- .

Conclusi贸n


  • , . - , , - .
  • 鈮 . code review , .
  • , , . .
  • . .
  • , ! , .


, Badoo PHP Meetup 16 . PHP-. , . ! 12:00, 鈥 YouTube- .

Source: https://habr.com/ru/post/443768/


All Articles