¡Hola, Habr!
Me llamo Maxim Ponomarenko y soy desarrollador en Sportmaster. Tengo 10 años de experiencia en el sector de TI. Comencé mi carrera en el área de pruebas manuales y luego me cambié al desarrollo de bases de datos. En los últimos 4 años, acumulando conocimientos adquiridos en pruebas y desarrollo, me dedico a la automatización de pruebas a nivel de base de datos.
He estado en el equipo de Sportmaster un poco más de un año y en uno de los grandes proyectos estoy trabajando en el desarrollo de pruebas automatizadas. En abril, mis compañeros de Sportmaster Lab y yo presentamos en una conferencia en Krasnodar, mi charla se titulaba «Pruebas unitarias en bases de datos», y ahora quiero compartirla con ustedes. Habrá mucho texto, por lo que he decidido dividir la presentación en dos publicaciones. En la primera hablaremos sobre las pruebas automáticas y las pruebas en general, y en la segunda me detendré más en nuestro sistema de pruebas unitarias y los resultados de su aplicación.
Primero, un poco de teoría aburrida. ¿Qué es la prueba automática? Es una prueba que se realiza mediante herramientas programáticas, y en la TI moderna se utiliza cada vez más en el desarrollo de software. Esto se debe a que las empresas crecen, sus sistemas de información crecen y, por lo tanto, también aumenta la cantidad de funcionalidad que necesita ser probada. Realizar pruebas manuales se vuelve cada vez más costoso.
Trabajé en una gran compañía cuyos lanzamientos se realizan cada dos meses. Al mismo tiempo, se dedicaba un mes entero para que un equipo de diez probadores verificara manualmente la funcionalidad. Gracias a la implementación de la automatización, un pequeño equipo de desarrolladores logró reducir el tiempo de prueba a 2 semanas en un año y medio. No solo aumentamos la velocidad de las pruebas, sino que también mejoramos su calidad. Las pruebas automáticas se ejecutan regularmente y siempre realizan todo el curso de verificaciones programadas, lo que significa que eliminamos el factor humano.
En la TI moderna es característico que se requiera del desarrollador no solo escribir el código del producto, sino también escribir pruebas unitarias que verifiquen dicho código.
¿Pero qué hacer si su sistema se basa principalmente en la lógica del servidor? No existe una solución universal ni mejores prácticas en el mercado. Por lo general, las empresas abordan este problema creando su propio sistema de pruebas personalizado. Aquí hay un sistema automatizado de pruebas personalizado que se creó en nuestro proyecto y del cual hablaré en mi presentación.

Probando la lealtad
Primero hablemos del proyecto donde implementamos el sistema de pruebas automatizado. Nuestro proyecto es el sistema de lealtad de Sportmaster (por cierto, ya hemos escrito sobre él en ).
Si su empresa es lo suficientemente grande, su sistema de lealtad tendrá tres propiedades estándar:
- Su sistema será de alta carga
- Su sistema contendrá procesos computacionales complejos
- Su sistema será sometido a mejoras de manera activa.
Vamos por partes... En total, si consideramos todas las marcas de Sportmaster, tenemos más de 1000 tiendas en Rusia, Ucrania, China, Kazajistán y Bielorrusia. En estas tiendas, se realizan alrededor de 300,000 compras diariamente. Es decir, cada segundo llegan a nuestro sistema de 3 a 4 tickets. Naturalmente, nuestro sistema de lealtad está sometido a alta carga. Y debido a que se utiliza de manera activa, debemos proporcionar los más altos estándares de calidad, ya que cualquier error en el software conlleva grandes pérdidas financieras, de reputación y otros.
Al mismo tiempo, en Sportmaster se llevan a cabo más de cien promociones diferentes. Las promociones son muy diversas: hay promociones de productos, otras relacionadas con días específicos de la semana, algunas atadas a tiendas específicas, otras basadas en el monto de la compra y otras por la cantidad de productos. En resumen, es bastante complejo. Los clientes tienen bonificaciones, hay códigos promocionales que se utilizan al comprar. Todo esto hace que el cálculo de cualquier pedido sea una tarea bastante no trivial.
El algoritmo que implementa el procesamiento de pedidos es realmente horrible y complejo. Cualquier cambio en este algoritmo es bastante arriesgado. Aparentemente, los cambios que parecen insignificantes pueden llevar a efectos bastante impredecibles. Y, de hecho, esos procesos computacionales complejos, especialmente aquellos que implementan funcionalidades críticas, son los mejores candidatos para la automatización. Verificar manualmente decenas de casos similares resulta muy costoso en tiempo. Y puesto que el punto de entrada al proceso permanece inalterado, al describirlo una vez, podemos rápidamente generar pruebas automáticas y estar seguros del funcionamiento de la funcionalidad.
Dado que nuestra sistema es utilizado activamente, el negocio querrá algo nuevo de su parte, mantenerse al día y ser orientado al cliente. En nuestro sistema de lealtad, los lanzamientos ocurren cada dos meses. Esto significa que cada dos meses necesitamos realizar una regresión completa de todo el sistema. Además, como en cualquier IT moderna, el desarrollo no llega directamente del desarrollador a producción. Se origina en el entorno del desarrollador, luego pasa secuencialmente por el entorno de pruebas, el de lanzamiento, el de aceptación y solo luego llega a producción. Al menos en los entornos de prueba y de lanzamiento necesitamos realizar una regresión completa de todo el sistema.
Las propiedades descritas son estándar para prácticamente cualquier sistema de lealtad. Hablemos de las particularidades de nuestro proyecto.
Tecnológicamente, el 90% de la lógica de nuestro sistema de lealtad es del lado del servidor y está implementada en Oracle. Hay un cliente desarrollado en Delphi que funciona como APM-administrador. Existen servicios web para aplicaciones externas (por ejemplo, el sitio web). Por lo tanto, es bastante lógico que si vamos a implementar un sistema de pruebas automatizadas, lo hagamos en Oracle.
El sistema de lealtad de Sportmaster ha estado en funcionamiento durante más de 7 años y fue creado por desarrolladores individuales... El número promedio de desarrolladores en nuestro proyecto durante estos 7 años ha sido de 3-4 personas. Sin embargo, en el último año, nuestro equipo ha crecido considerablemente y ahora están trabajando 10 personas en el proyecto. Esto significa que hay personas que se unen al proyecto sin estar familiarizadas con las tareas, procesos y arquitectura típicos. Existe un riesgo elevado de que podamos pasar por alto errores.
El proyecto se caracteriza por la ausencia de testers dedicados como personal fijo. Sin duda, existe la prueba, pero los analistas se encargan de ella, además de sus otras responsabilidades principales: interactuar con los clientes de negocios, usuarios, procesar los requisitos del sistema, etc. A pesar de que las pruebas se realizan con gran calidad (esto es especialmente relevante mencionarlo, ya que uno de los analistas podría ver este informe), la efectividad de la especialización y concentración en una sola tarea no se puede obviar.
Teniendo en cuenta lo anterior, para mejorar la calidad del producto entregado y reducir los plazos de desarrollo, la idea de automatizar las pruebas en el proyecto parece bastante lógica. En diferentes etapas de existencia del sistema de lealtad, algunos desarrolladores han puesto esfuerzos para cubrir su código con pruebas unitarias. En general, fue un proceso bastante fragmentado, donde cada uno utilizaba su arquitectura y métodos. Los resultados finales eran comunes para las pruebas unitarias: se desarrollaban pruebas, se utilizaban por un tiempo, se almacenaban en un repositorio de versiones, pero en algún momento dejaban de ejecutarse y se olvidaban. En primer lugar, esto sucedía porque las pruebas estaban más ligadas a un ejecutor específico que al proyecto.
Aquí entra utPLSQL

¿Sabes algo sobre Steven Feuerstein?
Este es un tipo inteligente que ha dedicado gran parte de su carrera a trabajar con Oracle y PL/SQL, y ha escrito una cantidad bastante considerable de trabajos sobre este tema. Uno de sus libros más conocidos se llama: «Oracle PL/SQL. Para Profesionales». Steven es el creador de la solución utPLSQL, que significa Unit Testing framework for Oracle PL/SQL. La solución utPLSQL fue creada en 2016, pero se sigue trabajando activamente en ella y se están lanzando nuevas versiones. En el momento de la presentación, la última versión data del 24 de marzo de 2019.
¿Qué es esto? Es un proyecto de código abierto independiente. Ocupa un par de megabytes, incluidos ejemplos y documentación. Representa físicamente un esquema independiente en la base de datos ORACLE con un conjunto de paquetes y tablas para organizar pruebas unitarias. La instalación toma apenas unos segundos. Una característica distintiva de utPLSQL es su simplicidad de uso.
En términos generales, utPLSQL es un mecanismo para ejecutar pruebas unitarias, donde una prueba unitaria se entiende como procedimientos de paquete Oracle estándar, cuya organización cumple con ciertas normas. Además de ejecutar las pruebas en utPLSQL, se almacena un registro de todas tus ejecuciones de prueba, así como un sistema interno de informes.
Veamos un ejemplo de cómo se ve el código de una prueba unitaria implementada según esta metodología.

Así que en la pantalla se muestra el código de una especificación típica del paquete con pruebas unitarias. ¿Cuáles son los requisitos obligatorios? El paquete debe tener el prefijo «utp_». Del mismo modo, todas las funciones de prueba deben tener este prefijo. En el paquete deben existir obligatoriamente dos procedimientos estándar: «utp_setup» y «utp_teardown». El primer procedimiento se llama al reiniciar cada prueba unitaria, mientras que el segundo se ejecuta al finalizar.
«utp_setup» prepara por lo general nuestro sistema para ejecutar la prueba unitaria, por ejemplo, creando datos de prueba. «utp_teardown» —por el contrario— devuelve todo a la configuración original y restablece los resultados de la ejecución.
Este es un ejemplo de la unidad de prueba más simple, que verifica la normalización del número de teléfono ingresado por el cliente al formato estándar de nuestro sistema de lealtad. No hay estándares obligatorios sobre cómo escribir procedimientos con pruebas unitarias. Por lo general, se llama a algún método del sistema que se está probando y el resultado devuelto por este método se compara con el estándar. Es importante que la comparación entre el resultado estándar y el obtenido se realice a través de los métodos estándar de utPLSQL.
En una prueba unitaria puede haber cualquier cantidad de verificaciones. Como se puede ver en el ejemplo, hacemos cuatro llamadas secuenciales al método que estamos probando para normalizar el número de teléfono y después de cada llamada evaluamos el resultado. Al desarrollar una prueba unitaria, hay que tener en cuenta que existen verificaciones que no afectan al sistema de ninguna manera, y después de algunas es necesario volver al estado inicial del sistema.
Por ejemplo, en la prueba unitaria presentada simplemente estamos formateando el número de teléfono ingresado, lo que no afecta de ninguna manera al sistema de lealtad.
Pero si estamos escribiendo pruebas unitarias para el método de creación de un nuevo cliente, después de cada verificación se creará un nuevo cliente en el sistema, lo que puede influir en la ejecución posterior de la prueba.

Así es como se ejecutan las pruebas unitarias. Se permiten dos variantes de ejecución: ejecutar todas las pruebas unitarias de un paquete específico o ejecutar una prueba unitaria específica en un paquete específico.

Así es como se ve un ejemplo del sistema de informes interno. A partir de los resultados del trabajo de la prueba unitaria, utPLSQL genera un pequeño informe. En él vemos el resultado de cada verificación específica y el resultado general de la ejecución de la prueba unitaria.
6 reglas para pruebas automáticas
Antes de comenzar a crear un nuevo sistema de pruebas automatizadas para el sistema de lealtad, junto con la dirección definimos los principios a los que nuestras futuras pruebas automáticas deben adherirse.

- Las pruebas automáticas deben ser efectivas y deben ser útiles. Tenemos desarrolladores maravillosos, de los cuales definitivamente hay que hablar, ya que alguno de ellos seguramente verá este informe, y ellos escriben un código excelente. Pero incluso su excelente código no es perfecto y contenía, contiene y contendrá errores. Las pruebas automáticas deben encontrar esos errores. Si no es así, o estamos escribiendo pruebas automáticas deficientes, o hemos llegado a un área muerta que, en principio, no se está trabajando. En ambos casos, estamos haciendo algo mal y nuestro enfoque es simplemente sin sentido.
- Las pruebas automáticas deben ser utilizadas. No tiene sentido gastar una gran cantidad de tiempo y esfuerzo en escribir un producto de software, ensamblar su repositorio y olvidar sobre él. Las pruebas deben ejecutarse, y ejecutarse con la mayor regularidad posible.
- Las pruebas automáticas deben funcionar de manera estable. Independientemente de la hora del día, el entorno de ejecución y otros ajustes del sistema, las ejecuciones de las pruebas deben dar siempre el mismo resultado. Generalmente, esto se garantiza porque las pruebas automáticas funcionan con datos de prueba especiales con configuraciones del sistema fijas.
- Las pruebas automáticas deben funcionar a una velocidad aceptable para su proyecto. Este tiempo se determina individualmente para cada sistema. Algunos pueden permitirse trabajar todo el día, mientras que otros deben cumplir plazos en segundos. Más adelante, comentaré qué estándares de velocidad hemos alcanzado en nuestro proyecto.
- El desarrollo de pruebas automáticas debe ser flexible. No es deseable renunciar a verificar alguna funcionalidad simplemente porque nunca lo hemos hecho así o por otras convicciones. utPLSQL no impone ninguna restricción en el desarrollo, mientras que Oracle, en principio, permite implementar una variedad de cosas. La mayoría de las tareas tiene solución; la cuestión es el tiempo y el esfuerzo invertido.
- Despliegue. Tenemos varios entornos donde es necesario ejecutar las pruebas. En cualquier momento, se puede actualizar un volcado de datos en cada uno de los entornos. Hay que gestionar el proyecto con pruebas automáticas de tal manera que se pueda realizar su instalación completa o parcial sin problemas.
Y en la segunda publicación en un par de días, contaré lo que hemos hecho y qué resultados hemos logrado.
Fuente: habr.com
