Testing Automatizado en GeneXus
Este artículo ha sido tomado principalmente de la charla dada por Abstracta en el Encuentro GeneXus 2009 Testing automatizado, hagamos que las máquinas trabajen por nosotros.
Intro: Discusión de "salados"
El término "salado" es utilizado como "referente" en un tema. A modo de introducción queríamos compartir lo que fue una "discusión entre salados".
El primer salado escribió en su blog (los salados escriben en blogs):
"Test automation is simply an automatic way of doing what testers were doing before” - Steve Rowe (Tester at Microsoft)
En un principio los testers tenían para probar un Software, entonces presionaban botones, invocaban funciones con distintos valores de sus parámetros y luego verificaban que el comportamiento sea el esperado. Luego estas funciones se volvieron más complejas cada vez más botones, los sistemas cada vez más sofisticados, y los testers no daban a basto. Los desarrolladores tenían que esperar mucho por el visto bueno de los testers para poder salir a la venta. Entonces la solución está en el testing automatizado, que consiste en algo tan simple como un programa que ejecuta las funcniones con distintos datos, toca los botones igual que un tester y luego verifica programáticamente si el resultado es el correcto. De ahí surge la frase antes citada. El segundo salado se ofendió al leer esto, considerando que los testers no pueden ser reemplazados por máquinas, y respondió en su blog criticando estas afirmaciones.
“Test automation means extending the reach of testers” - James Bach (Tester Consultant at Satisfice)
Respondió en su blog con algo muy interesante: "La automatización no hace lo que los testers hacían, a menos que ignores la mayoría de las cosas que realmente hace un tester. El testing automatizado es para extender el alcance del trabajo de los testers, no para sustituirlo".
Referencias:
- http://blogs.msdn.com/steverowe/archive/2007/12/19/what-is-test-automation.aspx (Published Wednesday, December 19, 2007 11:45 AM)
- http://www.satisfice.com/blog/archives/118 (This entry was posted on Wednesday, December 19th, 2007 at 5:55 pm)
Nosotros, desde nuestra humilde opinión estamos más de acuerdo con el segundo referente, ya que no creemos que la automatización sea capaz de sustituir el trabajo de los testers, sino de lograr que sea mucho mejor y de mayor alcance.
James Bach ha escrito bastante sobre su experiencia utilizando y desarrollando herramientas de automatización, por lo que se verán algunos de los desafíos que él mismo ha planteado en alguno de sus papers y artículos, y se verán algunas formas de solucionarlos, enfocando siempre a las particularidades de la comunidad GeneXus.
Existen muchos desafíos a resolver en la automatización, pero si se resuelven bien se pueden obtener grandes beneficios.
Definiciones introductorias
Testing de Regresión
En un principio pensaba que se refería a regresar a ejecutar las mismas pruebas. En realidad es verificar que lo que estoy probando no tenga regresiones.
Tampoco es verificar que se hayan arreglado los bugs que se habían reportado, pues lo importante es ver que lo que antes andaba bien ahora sigue funcionando, o sea que en ese sentido implicaría más ejecutar todo lo que antes andaba.
Hay quienes dicen que agarrar una listita con los pasos a seguir y las cosas a observar no están haciendo testing, sino un simple chequeo. Este hombre, Michael Bolton, uno de los salados en testing, comenta en este artículo las diferencias entre el testing y el chequeo. El testing es algo donde uno pone creatividad, atención, busca caminos nuevos, piensa “de qué otra forma se puede romper?”. Al chequear simplemente, nos dejamos llevar por lo que alguien ya pensó antes, por esa ya mencionada lista de pasos.
El tema también es que las pruebas de regresión viéndolas así son bastante aburridas.
El testing de regresión está atado al error humano. Es aburrido volver a revisar otra vez lo mismo! eso hace que uno preste menos atención.
A mi me pasa como tester que cuando se libera una nueva versión y ya pienso en todas las cosas que tengo que volver a probar a mano y lo aburrido que es esta tarea. Las personas se aburren de las tareas repetitivas, automatizables, de ejecutar las mismas pruebas.
Cuidado! No estoy diciendo que el testing sea aburrido! A mi al menos me encanta! Estoy diciendo que las cosas rutinarias son aburridas, y el aburrimiento lleva a la distracción y eso puede llevar a los errores.
Además los informáticos al menos tenemos como esa costumbre de ver las cosas que son automatizables, y pensar en cómo podría programar algo para no tener que hacer esta tarea a mano.
Ahí es donde podemos introducir testing automatizado, los robots no se aburren.
Automatización
Lo siguiente fue tomado de la definición de automatización industrial.
Adquirir tecnología para automatizar procesos manuales
Mejora:
- calidad
- performance en la producción
- rendimiento de los recursos humanos
La automatización refiere a una tecnología que permita automatizar procesos manuales, trayendo varias ventajas asociadas:
- Mejora la calidad pues hay menos errores humanos.
- Mejora la performance de producción pues con las mismas personas se puede lograr mucho más trabajo, a mayor velocidad y escala, y en ese sentido mejoran el rendimiento de las personas.
Observar que esta definición de la automatización industrial aplica perfectamente a la automatización del testing (o del checking).
Esto se volverá a ver más adelante, pero es lo que decía James Batch, la automatización no es para reemplazar a los testers, sino para hacer que ellos tengan más tiempo libre para otras tareas, y de esa forma las puedan desempeñar mucho mejor.
Desafíos y soluciones
A continuación se verán cuales son los desafíos que tenemos al querer aplicar esto de automatizar en las pruebas de regresión. Si la automatización la menospreciamos, la tomamos como una tarea a hacer cuando nos sobre un tiempito, o para ver cómo sale, seguramente fracasemos. La automatización presenta una serie de dificultades/desafíos que hay que tenerlos presentes para lograr avanzar con éxito. Veamos algunos de ellos.
Objetivo
Comencemos hablando de los objetivos. Como todo, hay que tener presente un objetivo. Pensar para qué queremos que nos sean útiles las pruebas automatizadas, y luego actuar en consecuencia.
Algunos ejemplos que se me ocurren, es que quiero seguir un enfoque de integración continua, y de esa forma tener una detección temprana de defectos. Entonces voy a tener un conjunto de casos de prueba que los voy a ejecutar todas las noches.
Otra opción (no son excluyentes, pueden ser complementarias) es tener un conjunto de casos de pruebas a ejecutar ante cada nueva versión del producto.
Puedo tener pruebas básicas, que me sirvan a modo de pruebas de humo, y de esa forma saber si la versión liberada a testing es válida para probar, y se prende fuego muy fácil.
Y otro de los objetivos podría ser que ciertos bugs no vuelvan al cliente. Si se reporta un error, este se corrije, y se automatiza una prueba que verifique que ese error no está presente. A quién no le ha pasado de que un cliente reporta un error, lo corregimos, y a los dos meses el cliente se queja furioso de que vuelve a pasar aquel error que ya nos había reportado!
Lo importante es arrancar con un objetivo en mente, y actuar para alcanzar ese objetivo.
Por esto el punto acá es antes de empezar el proyecto de automatización, tengan claro los objetivos y también tengan claro que indicadores van a utilizar para medir como se acercan o alejan a dichos objetivos.
Selección de Casos de Prueba
Luego, con el objetivo en mente, tal vez tenga más claro cuáles son los casos de prueba que quiero seleccionar para automatizar.
Es necesario ser ordenado y saber priorizar. Si uno se cuelga con algo a automatizar, y darle vueltas, porque lo encuentra desafiante y entretenido técnicamente, pero es una funcionalidad poco usada o poco crítica, entonces no se está actuando bien, tal vez no se esté avanzando hacia los objetivos.
Da más valor automatizar las funcionalidades más críticas. Es importante hacer un análisis de riesgo para decidir qué casos de prueba automatizar:
- importancia
- criticidad
- costo del impacto de errores
- probabilidad de que hayan fallos
- analizar con los desarrolladores - tal vez algo lo liberaron más a las apuradas, sin revisar
- SLA, contratos, plata en juego
- vidas en juego
También lo que se puede hacer es pensar en la probabilidad de que aparezcan bugs, y eso también está relacionado con la forma de uso. Pensar en cuáles son las funcionalidades más usadas, y dentro de eso los flujos más usados por los usuarios. Pero también eso combinarlo con la criticidad y costo e importancia (una liquidación de sueldo se corre tal vez una ves por mes, pero es muy importante que se haga bien).
Diseño de Casos de Prueba
Ahora, no se olviden de que no es sólo la selección lo importante, sino el tener definido qué pasos, qué datos, qué respuesta esperada
¿Ya tenemos casos de prueba de regresión documentados? si es así genial, y sino, esta es la oportunidad de formalizar el testing, de formalizar los casos de prueba en un lenguaje.
Los catedráticos del Test-Driven Development (desarrollo dirigido por pruebas), en donde se hacen primero las pruebas y luego se desarrolla en base a eso, plantean que el programar pruebas antes del código es una forma de documentar el comportamiento esperado, de documentar los casos de prueba. Luego dependerá del lenguaje quiénes son capaces de leer esa especificación.
Lo recomendable es comenzar simple! Si se apunta a comenzar simple se podrá adoptar más fácil la metodología. Las tecnologías simples se adoptan más fácil y rápido que las complejas.
KISS - keep it simple and stupid (tan de moda junto a las metodologías ágiles).
Automatizamos primero las "líneas amarillas". Después aplicar el What if, qué pasa si cambio tal dato, tal variante? ahi voy agregando partes a mi prueba, agregando variantes.
Una buena opción es comenzar en amplitud pero simple, luego ir agregando valor a cada prueba.
Es similar a la filosofía GeneXus, en cuanto al desarrollo incremental.
Selección de la Herramienta
Comenzamos hablando de los objetivos y de la selección de casos de prueba para automatizar, pero uno de los principales desafíos en la automatización es la selección de la herramienta, ya que para automatizar se necesita una herramienta.
Hay muchas herramientas, y si bien No no es el objetivo vender en esta charla (artículo), les voy a estar hablando de cómo nosotros encaramos todas las dificultades que se presentan en la automatización, por lo que al hablar de herramientas nos referiremos a Gxtest.
Ahora, si hay tantas herramientas, ¿por qué nosotros decidimos desarrollar Gxtest? El enfoque tradicional no es compatible con el desarrollo en GeneXus, pues implican grandes costos. GXtest está pensada para aumentar el beneficio de automatizar pruebas al desarrollar con GeneXus. Es la única herramienta que permite crear rápido, evolucionar y mantener los casos de prueba junto con la KB.
¿Cómo se logra esto? Trabajando con el mismo nivel de abstracción que Genexus.
Vamos a verlo con un ejemplo. Si tenemos una transacción Genexus para modelar los Clientes, veremos algo así.
Si automatizamos una prueba en la cual se hace clic en un control relacionado el cual se llama CliNom, en una herramienta tradicional vemos script el cual tendrá una acción asociada a un elemento HTML
En cambio, en Gxtest tendremos una acción asociada a un elemento de la KB.
Esto me trae grandes ventajas, como poder ejecutar las mismas pruebas sobre la aplicación generada en Java o en .Net, o incluso en distintas versiones de Genexus.
Ademas, generalmente es difícil mantener los artefactos de prueba al día, y si los tenemos relacionados a la KB, la herramienta nos ayudará a detectar y a impactar los cambios que se vayan produciendo en desarrollo, acomodando los Test, haciendo que evolucionen junto con la KB.
Si esta evolución no se logra, las pruebas automatizadas se van dejando de lado y se van volviendo obsoletas y se dejan de usar. Una de las ventajas del testing automatizado es que lo automatizado no nos cueste ejecutarlo cuantas veces queramos. Si no es fácil de mantener entonces perderemos más tiempo corrigiendo la automatización, que ejecutándola.
Por eso es que la selección de la herramienta es fundamental. Hay muchas herramientas, pero nosotros estamos convencidos de que con Gxtest se logra una diferencia significativa.
Datos de prueba
Al referirnos a sistemas Web, el caso más común son datos que el usuario ingresa a la aplicación a través de su interfaz. Luego de que uno automatiza una prueba debe ajustarla para que los datos de entrada puedan variar, y de esa forma la misma automatización nos es útil para probar muchos datos, y de esta forma verificar distintos casos.
Prácticamente todas las herramientas permiten obtener datos desde distintas fuentes, ya sea archivos, tablas, etc. En el caso de GXtest, se manejan estructuras llamadas Datapools. Estructuras simples con formato tabular. Otra forma de obtener datos es con invocación a procedimientos Genexus, y esto es otro punto donde se ve la integración de la herramienta con Genexus. Podríamos definir y usar en GXtest un procedimiento que busque cierto tipo de datos, con ciertas condiciones.
La mayor complicación acá es relacionar los datos de prueba con los datos de la base. Los datos de la base de datos de prueba pueden estar relacionados con los datos de entrada de los tests. Si estamos hablando de nombres de clientes como veíamos en un ejemplo anterior, y una de mis pruebas es ingresar un nombre de cliente que ya existe, entonces los datos que tengo que manejar en mis pruebas están enganchados con los datos que tengo en la base. En ese sentido tenemos que ser metódicos, y gestionar bien los ambientes de prueba.
Ambientes de prueba
Dentro de esa gestión tenemos que considerar muchos elementos que son parte del ambiente.
- La KB y la aplicación generada
- Los artefactos de prueba y los datos que estos usan
- A su vez los datos están relacionados con la base de datos del sistema bajo pruebas.
Agreguemos la complicación de que tal vez tenemos distintas pruebas a realizar con distintas configuraciones, parametrizaciones, etc. Entonces para esto tenemos más de un ambiente de pruebas, o tenemos un ambiente y muchos backups de base de datos, uno para cada conjunto de pruebas. La complejidad extra que agrega esto es que hay que mantener cada backup, aplicar Reorganizaciones cada vez que aplique, etc.
Pero si uno de estos elementos no está en sintonía con el resto, las pruebas fallarán, y no estaremos siendo eficientes con nuestros esfuerzos. Es importante que cada vez que una prueba da fail, es porque hay un bug.
Por esto resulta interesante hablar de los oráculos.
Oráculos de prueba
En el testing es el resultado de una prueba, si falló o pasó, es lo que determina si pasó o falló.
Al ejecutar pruebas el tester tiene un modelo mental de la aplicación y de la realidad, de lo que es correcto e incorrecto. Esto le permite ejecutar acciones y determinar si el resultado está bien o mal en base a ese modelo mental. Cuando se define un caso de prueba el tester expresa las acciones a ejecutar, pero ¿qué pasa con el oráculo? es necesario definir (imaginarse) las acciones de validación que me permitan dejar bien plasmado un oráculo capaz de determinar si se recibe lo correcto o no. Hay que agregar las validaciones suficientes para dar el veredicto, en cada paso, persiguiendo ese objetivo de evitar tanto los falsos positivos como los falsos negativos, que una prueba de error cuando no hay error, o que no de error cuando sí lo hay.
Cuándo ejecutar
Pasemos ahora a otro punto que no tiene tanto que ver con los detalles “técnicos” del testing. Veamos temas de planificaión. Es necesario planificar las ejecuciones, pero no solo eso. Lo ideal es que el testing sea considerado desde el comienzo, y si se desea automatizar, que considere también cada una de las tareas relacionadas.
Mucha gente sigue con la concepción de que el Testing es algo que hay que dejar para el final, si es que da el tiempo, y en realidad es una tarea que hay que hacerla y planificarla desde el comienzo.
En cuanto a la automatización, algunas de las tareas a planificar son las que se ven a continuación:
- Automatización
- Mantenimiento
- Ejecuciones
- Verificación y Reporte de bugs
- Correcciones de bugs detectados
Hay que ver cuándo comenzar a automatizar, desde el comienzo, luego de cierta etapa en la que se espera ya tener más estabilidad, y pensar en el mantenimiento que me va a llevar todo eso también. Esto está bastante ligado a la herramienta que se elija y las facilidades que brinde para cada cosa.
¿Cuándo ejecutar?
- Al tener pocos test, o que llevan poco tiempo ejecutar: TODOS
- Si llevan mucho tiempo ejecutar:
- Priorizar
- Análisis de impacto
Piensen en que mayor cantidad de ejecuciones más ROI voy a tener de la automatización. Y como siempre, no alcanza con testear, también hay que corregir, y ese esfuerzo hay que considerarlo al planificar. Y además de planificar cuándo hay que pensar en quién?
¿Quién se dedica a automatizar las pruebas?
Según James Batch, en alguno de los artículos que escribió este salado, no es necesario tener un equipo separado o especial para automatizar, lo ideal es que los mismos testers puedan encarar con estas tareas para que las pruebas automatizadas tengan en cuenta cosas que están en la visión del tester, y no en alguien que conozca de la herramienta y nada más, y sólo un poco de la aplicación a testear.
Ees importante tener un team con skills en:
- la aplicación y el dominio de negocio
- la herramienta de automatización
- Genexus (para conocer los problemas técnicos típicos)
- testing (técnicas de generación de casos de prueba)
Cada skill va a aportar valor en distintos sentidos.
Es por eso que podríamos tener un flujo de trabajo como el de las imágenes
En este cada equipo aporta y aprovecha de las pruebas automatizadas.
Cada desarrollador podría tener algo específico para explotar sus módulos. Luego al integrar eso en un ambiente consolidado se podría tener otro conjunto de pruebas que funcionen como un filtro para no pasar a testing cosas muy verdes, lo cual sería pruebas de humo. Luego testing tiene sus propias pruebas automatizadas. Y en el ultimo puesto de la cadena, podríamos tener al cliente, que tiene sus propias pruebas automatizadas como parte de sus pruebas de aceptación, o qué tal incluso que la software house le entregue al cliente además de la aplicación un conjunto de casos de prueba que validen las nuevas funcionalidades.
Además el hardware del cliente puede ser complejo, y por eso cuentan con un ambiente de pre-producción para probar sobre hardware similar al de producción el comportamiento de la aplicación.
Motivación y compromiso del equipo
Ahora, todo esto se puede lograr sólo si todo el equipo se comprometa con el proyecto de automatización. La automatización en sí es un producto nuevo al cual hay que seguir desarrollando, manteniendo, hay que verificarle la calidad, etc.
Compromiso equipo desarrollo -> ayudando y respondiendo dudas al equipo de testing, programando en forma testeable.
Compromiso equipo testing -> resultados, ¿son sólo marcas rojas en un reporte? O son bugs que deben ser reportados, con el mayor análisis posible como para que sea fácil de corregir ASAP.
Compromiso en la gerencia -> planificando y asignando tiempos a los dos equipos para cada una de sus tareas, marcando las prioridades
No es algo que se pueda hacer en los tiempos libres.
Las personas tienen la necesidad de sentir que están aportando algo al proyecto.
Se pierde este sentimiento al volver a hacer lo que ya se hizo: ejecutando pruebas de regresión, corrigiendo scripts automatizados, etc.
Como tester siento que estoy aportando:
- Si obtengo resultados antes
- Si encuentro bugs más temprano
- Si doy mejor información sobre el estado de la aplicación
- ¿Estamos listos para salir al mercado?
Otras consideraciones
Vamos a ir redondeando con unas últimas consideraciones.
- 1 - ¿Qué hago con un bug?
- Si un reporte me dice que hubo un fallo, lo primero es determinar si el fallo se debió a los Test Cases. Hay que asegurarse que la culpa no es del test antes de avisarle sobre un bug a un desarrollador, eso mejora las relaciones :) Además, hay que verificarlo manualmente, para ver si se puede identificar la causa, para ver si ocurre siempre, hay que ver si fue un tema de datos, ambiente, casualidad, etc. Luego, hay que ver de encontrar la cantidad de pasos mínima para reportarlo, ya que si haces más fácil el encontrar la causa que lo genera, va a ser más facil de resolver para el desarrollador, y más fácil para el reproducir luego esa situación, como para darse cuenta si lo está resolviendo o no.
- 2 - ¿Cuándo se hacen visibles los resultados?
- Tal vez uno piense que si las pruebas me encuentran un error ahí estoy encontrando beneficios, entonces voy a poder medir la cantidad de bugs detectados por las pruebas automatizadas. En realidad el beneficio se da desde el momento de modelar, y especificar con un lenguaje formal las pruebas a realizar. Luego, al ejecutar, también agrega valor la información que dan las pruebas. NO es sólo útil el resultado de error detectado, sino el resultado de OK que me está diciendo que lo que yo automaticé a probar se está cumpliendo. Un artículo de M&T (http://www.methodsandtools.com/archive/archive.php?id=33) dice que se encuentran gran cantidad de bugs al momento de automatizar los test cases. Al automatizar uno debe explorar la funcionalidad, probar con distintos datos, etc. Generalmente lleva un tiempo en el que uno está "dándole vueltas" a la funcionalidad a automatizar. Luego, para probar que la automatización haya quedado bien se ejecuta con distintos datos, etc. En ese momento ya estamos haciendo un trabajo de testing muy intenso.
- 3 - Se le preguntó a la audiencia ¿Qué creen? Con el testing automatizado, logramos encontrar más bugs??
- En este artículo dice que no, yo creo que si. La única forma de que eso no sea cierto es que alguien manualmente ejecute cada vez todo lo que se podría automatizar. Si se hace en forma manual, seguramente sea muuucho mejor, en el sentido que al ejecutarlo manual se pueden encontrar otras cosas. Porque recuerden que las pruebas automatizadas hacen checkeo y no testing. çSeguramente lleve más tiempo hacerlo manualmente. Pero lo que sí puedo garantizar es que si se automatizan pruebas se van a encontrar más bugs.
- Cuidado! Si automatizo pruebas sobre un módulo y considero que con esas pruebas es suficiente, entonces ¿no lo pruebo más? el riesgo es que las pruebas automatizadas no estén cubriendo todas las funcionalidades (paradoja del pesticida). Dependencia con la calidad de los test. Tal vez tengo mil pruebas, y por eso creo que tengo un buen testing, pero esas pruebas tal vez no verifican lo suficiente, son muy light o todas similares.
- 4 - No se reemplaza al testing manual
- El testing automatizado que planteamos es un testing automático estático, esto es porque siempre hace lo mismo, siempre ejecuta los mismos casos de prueba, los mismos datos de prueba, y verifica siempre las mismas cosas (a menos que los vayamos evolucionando). No es el objetivo de la automatización el remplazar el testing manual, sino dejar más tiempo para que el mismo de mejores resultados. La herramienta de automatización es como un tester extra, un tester virtual.
- Imaginen que el tester tiene 1 día para testear. Tiene que elegir entre testear la funcionalidad nueva, o testear las funcionalidades críticas del sistema. Claro, las funcionalidades críticas del sistema se vienen probando desde las primeras versiones de la aplicación, últimamente no tenían ningún problema. Además, la funcionalidad nueva tiene un componente motivacional interesante, seguramente le encuentro bugs. Tiene un control nuevo, un calendario, que seguramente si voy para atrás, creo, modifico, etc., algo le voy a encontrar. Y la funcionalidad crítica ya la hago de ojos cerrados, pero es un muy aburrido probarla porque es un flujo larguísimo sobre la aplicación que ya lo hice muchas veces. Claro, los nuevos cambios sobre el sistema me impactaron la funcionalidad crítica, esta tiene un bug bloqueante (ya no puedo crear facturas por ejemplo), y liberamos así una funcionalidad, lo cual es muy malo.
Resumen
Ahora que ya vimos todo esto, vamos a hacer un chequeo de regresión, por más que se que hacerlo a mano es aburrido.
A – metas / objetivos
U – casos de prueba
T – herramienta
O – datos de prueba
M – ambientes
A – oráculos
T – ¿cuándo? planificar
I – ¿quién? compromiso
O – motivación
N – consideraciones
- Iniciar con un objetivo en mente y actuar en consecuencia
- Priorizar los casos de prueba a automatizar
- Seleccionar una herramienta adecuada
- Variar los datos de prueba
- Cuidar y gestionar los ambientes
- Plasmar bien los oráculos en las pruebas
- Planificar, asignar tiempos para todas las tareas relacionadas
- Quién aportará y se beneficiará con las pruebas
- Pensar en la motivación
- Y en el resto de las consideraciones que vimos
El resultado es “succeded”, estamos listos para ponernos a automatizar!