jueves, 20 de abril de 2017

Cápsulas de pruebas - Estrategias de Datos v2


En los equipos que desarrollan ágilmente se busca que todos los miembros del equipo tenga un conocimiento mínimo de las actividades de testing. También que los testers profundicen su conocimiento.

¿Cómo podemos distribuir ese conocimiento?
Las cápsulas de información de testing son una manera incremental de incorporar conceptos a partir de ejemplos del equipo o externos. Pueden servir como guía para realizar círculos de aprendizaje en el equipo de desarrollo o para profundizar conocimientos en comunidades de práctica.
Algunas cápsulas de conocimiento: Arquitectura de la prueba Automática, Modelo del Oráculo y Pruebas Diagnósticas.

En este caso, nos encontraremos 45 min el 21 de abril de 2017 (¡mañana!) para hablar sobre las estrategias de preparación de datos para pruebas automatizadas, de 13:15 a 14:00hs Bs As.

Agenda

  • Presentar el concepto (10 min).
  • Trabajar en grupos para analizar el ejemplo, o un caso particular (20 min).
  • Presentar los resultados (10 min).
  • Cierre (5 min).
Anotate

(Próximo encuentro, viernes 28 de abril, votá los temas)



Cápsula de Pruebas - Datos de Prueba

¿Cómo generar los datos de prueba?
¿Cómo lograr que los datos estén en disponibles en el momento de la prueba?


¿Cómo lo he hecho?

Para ejecutar las pruebas automáticas, necesitamos que la aplicación o SUT (System Under Test) esté en un estado conocido. Ese estado incluye los datos necesarios para la prueba.


Toma una prueba que estés realizando en este momento o que realizaste hace poco, piensa y anota:
  • ¿Cómo obtuviste o generaste los datos de prueba?
  • ¿Cómo lograste que esos casos de prueba estén cargados o disponibles para el SUT?


Generación de datos

Por Diseño: Se inventan datos que ejercitan la funcionalidad a desarrollar. Los ejemplos pueden estar basados en la experiencia en el negocio o en las hipótesis de uso futuro. Por ejemplo, generar datos que corresponden a situaciones límites y de error, hayan ocurrido o no.


Datos Reales: Tomar un conjunto de datos de la aplicación actual o del problema a resolver. Por ejemplo, tomar los conceptos facturados  en el último mes, o los clientes y movimientos de una sucursal durante el año pasado.


Simulados: Utilizar un algoritmo para generar datos. Por ejemplo, todas las combinaciones posibles de los variables de entrada, o valores aleatorios.


Object Mother: Cada entidad de la aplicación tiene un mecanismo para generar objetos de prueba. Normalmente con datos default y las entidades adicionales las genera recursivamente. Por ejemplo, una prueba que necesita un cliente, la prueba le pide a la entidad Cliente una instancia de prueba. Cliente genera un cliente que tiene un nombre y apellido default (Juan Perez). Para completar el país de nacimiento,  Cliente le pide a la entidad Pais una instancia de prueba.


Estado conocido

Cargar cada vez: Cargar los datos para cada prueba. Esto puede hacerse a diferentes niveles: desde el repositorio de los datos (base de datos, archivos), desde una capa de servicios o componentes, a través de la funcionalidad disponible para el usuario final. Puede cargarse a partir de un estado inicial vacío, o como incremento. Puede ser necesario modificar datos (fechas, números de referencias cruzadas).


No cambiar: Se llega al estado conocido y se lo proteje. Por ejemplo backup y restore de bases de datos, se utilizan transacciones de base de datos, se realizan operaciones que no modifiquen datos o se realizan operaciones que revierten la operación realizada en la prueba.


Existentes: Asumiendo que tenemos un volumen alto y variado de datos, realizamos una búsqueda que nos traiga un dato con las características que necesitamos.


Mock (o dobles): Reemplazamos un componente del sistema, que no nos interesa probar, por un mecanismo que devuelva datos conocidos. Pueden ser siempre los mismos datos o puede ser más inteligente.


Actividades

Analiza el siguiente ejemplo y proponer la estrategia para los datos de prueba:


Tenemos una aplicación monolítica que resuelve una parte central del negocio de nuestra organización. Siguiendo las buenas prácticas actuales, se busca migrar hacia una arquitectura de microservicios. La migración será incremental, y en cada micro servicio se va a realizar en dos fases: duplicar funcionalidad mínima de la aplicación actual, y luego agregar funcionalidad nueva, valiosa para el negocio.
La aplicación actual tiene algunas pruebas automatizadas a través de la UI.
Queremos que puedan trabajar en paralelo los equipos que modifican el sistema monolítico remanente y los que desarrollan cada nuevo micro servicio.
¿Qué alternativas tenemos para generar los datos de prueba?
¿Cuáles son los pros y contras de cada una de las alternativas?

jueves, 30 de marzo de 2017

Capsulas de pruebas - Estrategias de Datos


En los equipos que desarrollan ágilmente se busca que todos los miembros del equipo tenga un conocimiento mínimo de las actividades de testing. También que los testers profundicen su conocimiento.

¿Cómo podemos distribuir ese conocimiento?
Las cápsulas de información de testing son una manera incremental de incorporar conceptos a partir de ejemplos del equipo o externos. Pueden servir como guía para realizar círculos de aprendizaje en el equipo de desarrollo o para profundizar conocimientos en comunidades de práctica.
Algunas cápsulas de conocimiento: Arquitectura de la prueba Automática, Modelo del Oráculo y Pruebas Diagnósticas.

En este caso, nos encontraremos 30 min el 31 de marzo de 2017 (¡mañana!) para hablar sobre las estrategias de preparación de datos para pruebas automatizadas.

Anotate



jueves, 26 de enero de 2017

TestComplete y Git

En un grupo están trabajando con TestComplete, una herramienta que permite automatizar aplicaciones de escritorio (y muchas más cosas).
Estaban manteniendo las pruebas con versionado por directorios y decidimos moverlos a git.

La solución es sencilla, ya que TestComplete tiene integración con git.

Agregar en la raíz un archivo .gitignore con contenido
Log/

Luego se pueden seguir los pasos normales para subir un proyecto existente a un repo. Por ejemplo en GitHub.


¿Y que pasa si te olvidás del paso del .gitignore?

En ese caso, la subida de los logs puede tardar mucho tiempo, incluso dar timeout. En nuestro caso, contenido completo de la carpeta del proyecto con sus logs pesaba 500Mb!

¿Cómo borrar completamente algo de Git?

Quitar de la versión

En este caso, para borrar todos los directorios Log


find . -name Log -print
Tomar de la salida todos los directorios resultantes y armar lineas como la que está a continuación, que quitan los directorios del repo local, pero lo dejan fisicamente.
git rm -r --cached <directorio>/Log

Luego podés validar que estén borrados en Git.
Ahora si, agregá el .gitignore (como está indicado arriba).
Y comitear y subir al repo. 
git status
git commit -m ‘borrar logs’
git push

Validar que en repo remoto no esten los Logs.


Quitar de toda la historia

No es común querer modificar la historia de Git. Y la forma estandard brindada por git es lenta.
Usamos una herramienta llamada BFG.

git clone --mirror https://github.com/<user>/<repo> <repo>_mirror
cp -a <repo>_mirror/ <repo>_backup/
cd <repo>_mirror
java -jar ~/Downloads/bfg-1.12.14.jar --delete-folders Log
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push


En nuestro caso, pasamos de un repositorio de más de 1Gb a uno de 380Mb.

miércoles, 18 de enero de 2017

Desarrollo ágil de Software - stack Python

Soy uno de los facilitadores del curso Desarrollo Ágil de Software (DAS) de Kleer.
Lo solemos hacer con Ruby (alguna vez lo hemos dado en Java y C#).

Afortunadamente, hace poco lo hicimos en Telefonica I+D Chile y nos pidieron hacerlo con Python ¡Gracias!

Le comento mi experiencia y les dejo la referencia del ambiente https://github.com/jgabardini/csdpy, lo pueden reproducir en Linux (o la virtual de DAS con Mint)

Resumen de Stacks

En el ambiente Ruby, las herramientas son: bundle, rspec, cucumber, webrat/capybara, sinatra con erb.

En el ambiente Python: virtualenv y pip, behave, splinter, flask con jinja2. Además, usé un plugin de Jenkins: ShinningPanda.

Python

No hubo problemas porque la mayoría ya programaba en Python (había dos o tres personas sin conocimiento, pero que se sumaron rápido).
Algunos prefirieron usar sus ambientes, por los editores (sin usar la virtual). La virtual tiene Gedit, ellos usaban Visual Studio Code, vim, ....
Usé Python 3.4 (en vez de 2.7 que es el default en la virtual de DAS).
Para manejar versiones y ambientes use virtualenv y pip.

Unittests

Usé nosetests como test runner. Extrañé la sintaxis BDD (de rspec), pero ellos no 😉
Para el próximo (que por suerte es la semana que viene), daré instrucciones concretas sobre la estructura de directorios. Los desarrolladores Python NO tienen el mantra Convention over configuration, cada uno lo hace distinto si los dejas libres 🙌. Y explicaré las reglas de descubrimiento de pruebas de nosetests, eso hubiera ayudado (tests/xxx_test.py).

Flask

El código mínimo es un poco más largo que el de Sinatra y, como yo no tengo tanta práctica, no lo escribí de cero. Usé el código del repo csdpy desde el inicio.
Cuando falla el routing u otro error, no es tan amistoso como Sinatra, no muestra una página 500 con información de que falta.
Usar annotation para definir el routing, obliga a tener funciones por cada mapeo, y es natural que la misma función cubra varios métodos HTTP. Cometí muchos errores de nombre método duplicado, acostumbrado a los bloques de Ruby.
Los asistentes no tuvieron mucho problemas (o los resolvieron).
Nuevamente, Flask es menos prescriptivo que Sinatra. Yo propuse una estructura de directorios. 
El motor de templates, Jinja2, lo usé simplificado. Sin layout, bloques ni herencia. Es el motor usado en  Django.

Behave

Sigue bastante la idea de Cucumber, excepto que los pasos son distintos para cada palabra clave (Given/When/Then). En Cucumber, un paso está definido solo por el texto. En Behave los pasos se definen por la combinación palabra clave + texto. Tuve el mismo problemas con nombres de métodos repetidos que en routing de Flask.
No propone pasos con regex  "automáticas". Uno debe agregar los parámetros a mano.

Splinter

Usé Splinter que equivale a webrat/capybara. Pinta muy bien. Tiene una API muy parecida a WebDriver y puede usar los driver de WebDriver, o flask (me parece que inprocess, pero no lo encontré la documentación).


Configuración de Jenkins

Para correr tareas que requieren virtualenv, use un plugin ShinningPanda. Todas las tareas configuradas como shell.
Para que corra el behave tuve que agregar un package: behave-jenkins.

Conclusiones

Hacer la migración de Ruby a Python me llevó un día neto de trabajo. Bien sencillo.
Luego de 3 años de programar principalmente con Ruby, me sentí raro en Python. Me falta práctica. Por suerte, la semana que viene volvieron a pedirme, esta vez en Córdoba, que hagamos el curso en Python 😎


lunes, 28 de diciembre de 2015

Ya no estamos en testing Kansas

Nota: El título hace referencia a "We're not in Kansas anymore", del Mago de OZ.


¿Dónde estamos?

La agilidad surgió como una revolución de una clase oprimida; la de los programadores que lucharon para liberarse de los Project Managers.

Han pasado 15 años desde el Agile Manifesto. La revolución ha cumplido su objetivo. Los programadores lograron ser reconocidos como miembros igual de importantes dentro de los equipos de desarrollo. Pero, ¿Qué pasó con los testers?

En el primer proyecto ágil en el que participó uno de los autores, el grupo estaba cambiando su forma tradicional de desarrollo de software a una dinámica ágil. Era inicialmente un grupo compuesto por tres equipos de programación y uno de testing.
Durante el cambio, algunas personas del equipo de testing se sumaron a los programadores para formar equipos de desarrollo que incorporen la calidad desde el inicio. Pero el cambio no fue completo, los testers se ocuparon en acercarse a los programadores automatizando pruebas. Pero en los últimos dos días de cada sprint, cuando se corrían las pruebas finales (automáticas y manuales) antes de liberar el producto, algunos miembros del equipo no tenían respiro (los testers), mientras otros miembros del equipo se dedicaban a jugar al Counter Strike. Eso sí, con auriculares para no molestar. En este contexto, donde la calidad esperaríamos que fuera interés de todos, las tareas de testing no las toman los programadores.
La historia que contamos muestra una implementación incompleta del enfoque Whole Team o equipo completo. Pero ¿qué pasa si logramos una buena implementación? Si todos los miembros del equipo se ocupan de la calidad, entonces ¿el tester desaparece?


El rol de tester en un equipo ágil

Si definimos lo que somos por lo que hacemos (testeo, por lo tanto soy tester) no sólo nos auto-limitamos en nuestro crecimiento personal sino que además limitamos la capacidad de nuestro equipo para encarar desafíos.  

El equipo debe tener los conocimientos y capacidad para testear, los cuales no necesariamente deben estar centralizados en una persona, sino que pueden ser parte de un rol y ese rol puede estar distribuido en varios miembros del equipo. De esta manera todo el equipo es responsable de la calidad.

El rol de testing ágil tiene algunas diferencias con el testing tradicional. En lugar de una persona exclusivamente preocupada por el detalle, el rol de testing ágil ajusta el nivel de detalle según el análisis que se esté realizando. En lugar de enfocarse en probar el producto, se ocupa en que el producto se construya con calidad.

En el testing ágil además de ser importante probar que hicimos lo que nos pidieron, resulta central considerar las razones y el contexto en el que nos lo pidieron. De esta manera, puede detectarse si estamos logrando el objetivo original, si tenemos la oportunidad de lograr un producto que exceda las expectativas y en general, sí mantenemos la mirada en la visión y los pies en la tierra. Luego, podemos distinguir el grado de importancia de los distintos temas identificados y tomar decisiones considerando esa guía: ¿Qué nos acerca a la visión? ¿Qué nos dificulta avanzar?
En resumen, consideramos que las siguientes características resultan centrales para el rol de testing ágil:

  • Comprender la visión de negocio: ¿Que proceso de negocio es el prioritario? ¿Cuáles son los objetivos y sus métricas relevantes que cierta funcionalidad intenta mejorar?
  • Conocer el proceso de desarrollo: Dentro del rol de testing ágil está trabajar continuamente para que la calidad esté incorporada al proceso de desarrollo. Si detectamos un problema en el ambiente de aceptación, tratemos de agregar un test para que la próxima vez se detecte en el ambiente de desarrollo. Optimizar el proceso muchas veces implica automatizar la prueba de regresión. Y avanzando por este camino, vemos que la calidad desde temprano nos permite más velocidad, como puede verse en Continuous delivery.
  • Saber cómo diseñar experimentos: Esto nos sirve para validar hipótesis del negocio (Lean Startup), para probar que estamos haciendo el producto correcto y bueno para nuestros clientes, como para mejorar nuestro proceso de desarrollo. También tenemos hipótesis sobre aspectos que afectan la calidad y hacemos experimentos probando el producto.
  • Conocer sobre testing en sí mismo: Es más fácil conseguir capacitación sobre programación o gestión de proyectos que sobre testing. Hay poca bibliografía y poco tiempo dedicado a la mejora del testing (katas, dojos, craftsmanship). Sin embargo hay mucho para aprender: evaluar las dimensiones de variación del sistema, identificar dimensiones válidas para probar, definir si es posible probarlas de forma independiente, etc. También resulta necesario conocer las diferentes heurísticas de prueba, los problemas comunes que dependen de la tecnología usada e identificar el conjunto que es posible probar en cada momento del desarrollo.
  • Riesgos: ¿Cuál es nuestra peor pesadilla? ¿Cuáles son las formas en que se puede romper el producto?¿Qué podemos perder, vidas, dinero, clientes? Las respuestas a estas preguntas nos orientan tanto en la definición de alcance de las pruebas como para su priorización. Conociendo los riesgos podemos elegimos cómo manejarlos. Tomar riesgos en forma controlada nos permite ir más lejos más rápido y ser más innovadores, que si quisiéramos evitar todos los riesgos. Ver mi post anterior sobre el tema.

¡Cómo que en la lista no está ...!

Algunas dudas surgen de esta enumeración: ¿qué pasa con la automatización de la prueba, la usabilidad, la seguridad?
En un equipo de desarrollo ágil es bueno que todos se ocupen en aprender sobre programación, testing, usabilidad, seguridad y probablemente otras cosas también. 
Automatizar, automatizar, automatizar: Es el mantra de todos los miembros del equipo. Es parte de lo que llamamos Conocer el proceso de desarrollo. Para ello es útil que todas las personas de equipo puedan escribir scripts al respecto, pero no necesariamente ser todos expertos en herramientas. Como testers, podemos trabajar de a pares con los expertos.
Pero no todos tienen que ser expertos en todo. Nos parece útil, por lo tanto, dejar esos temas en otros roles. Cada persona desarrolla su especialidad, profundizando y participando de comunidades de práctica. Además, aprende de sus compañeros de equipo sobre otras áreas. Entonces una persona que cubre principalmente el rol de testing, puede además conocer sobre programación lo suficiente como para automatizar situaciones normales y pedir ayuda ante problemas técnicos complejos.

¿Pero es tan distinto el testing en ambientes ágiles del testing tradicional?
Una pregunta que naturalmente surge es: ¿Cuáles de estas características no están en el rol tradicional?¿Son exclusivas del rol del testing en un ámbito ágil?

Consideramos que ninguna de las actividades es demasiado novedosa, por lo que podríamos identificar actividades equivalentes en el marco del testing tradicional. Y encontramos dos diferencias: 

No hay en el equipo una persona cuya única tarea sea probar y que concentre toda la prueba necesaria. Sí se encuentra definido un rol, que cubierto por diferentes personas, con distinto grado de involucramiento. Así es posible compartir más tiempo con otros y esto da lugar a más oportunidades de aprender, crear e innovar.

¿Y ahora qué?
Considerando la diversidad de conocimientos necesarios para cubrir de manera completa el rol del testing, es posible identificar quienes son los miembros del equipo más adecuados para cubrir esas necesidades y que ellos se interesen, no sólo por profundizar el conocimiento sobre esos temas, sino además compartirlos con los compañeros de equipo
.

Una forma es a través de lecturas. Mi lista personal de libros: Agile Testing, More Agile Testing, Explore It!, How Google Tests SoftwareThe Domain Testing Workbook, Continuous Delivery.

Además, junto con Natty y Ángel realizamos cursos on line de Agile Testing.


Origen del post y agradecimientos

Este post es uno más, dentro de mi búsqueda sobre el testing (ver lo que opinaba en 2009). Entre 2014 y 2015 presenté algunas de estas idea en JAIIO 43, Ágiles 2014 (en Open Space con Juan Diego Vasco Moncada), CAS2014 (ver la presentación más abajo) y Agile 2015.
Gracias a Natty Davidovich (), Ángel Nuñez Salazar () y Nico Paez () por las discusiones, revisiones y aportes a este post y a mi comprensión del testing.


lunes, 30 de noviembre de 2015

Difusión de las innovaciones

La difusión de las innovaciones o adopción de ideas y tecnologías sigue ciertos patrones. Distintos autores los estudiaron. El trabajo clásico sobre el tema es de Everett Rogers (Wikipedia).

En este post voy a comentar una versión alternativa que presentó Geoffrey Moore en 1991 en su libro "Crossing the Chasm".
El gráfico representa la cantidad de personas que adoptan a medida que avanza el tiempo.
En l propuesta inicial de Rogers, al principio lo adoptan los innovadores (Innovators), luego los primeros seguidores (Early adopters), la mayoría temprana (Early majority), la mayoría tardía (Late majority) y finalmente los rezagados (Laggards).
Un aporte importante de Moore es identificar que entre los primeros seguidores y la mayoría temprana se produce un quiebre importante, en el muchas innovaciones se detienen. Lo llama la brecha (the chasm).

La idea central es que las personas que adoptan ideas o tecnologías en diferentes momentos tienen necesidades distintas y que siendo conscientes del momento en que se encuentra el producto, podremos ajustar mejor la estrategia, tanto de mejora como de comunicación, para llegar a nuestros siguientes 'compradores' de la innovación:

  • Innovadores: los que siempre buscan lo nuevo, les interesa ser "los primeros en ...". Es fácil lograr que usen nuestro producto o idea, pero no les dura mucho ya que pasan a algo nuevo rápidamente. Pero mientras lo usan, lo hacen conocido a más personas y alguno de ellos se vuelve un primer seguidor. Nuestra tarea es entusiasmarlos con la potencialidad y lo novedosa que es la innovación. 
  • Primeros seguidores: a los que nuestra innovación les genera mucho beneficio. No se detienen ante los riesgos o las imperfecciones que seguramente tiene la innovación en esta instancia. Nuestra tarea es escucharlos y ajustar la innovación para que les genere más y más valor aún.
  • La brecha: es un momento de decisiones difíciles. Si seguimos ajustando la innovación a lo que nos pide cada uno de los primeros seguidores, nunca llegaremos al gran público. En tecnología, seguiremos agregando más y más funcionalidad o detalles, cada uno de ellos relevantes solo para un pequeño número de interesados. Necesitamos un cambio de foco, que nos alejará de nuestro soporte actual (los primeros seguidores) y quizás pase un tiempo hasta que ganemos a la mayoría temprana. Nuestra tarea es trabajar en hacer la innovación sencilla de comunicar, de adoptar y de usar, confiable, con soporte ante inconvenientes.
  • Mayoría temprana: a los que nuestra innovación les genera valor, pero no están dispuestos a tomar riesgos elevados. Los convencen las historias de éxitos de otros que ya pasaron por la adopción. Están dispuestos a pagar por la innovación. En esta etapa el crecimiento de la adopción es explosivo. Moore escribió sobre esto en su libro "Inside the tormado". Nuestra tarea es escalar para sostener la demanda. El limitante para el crecimiento en adopción es nuestra capacidad para escalar.
  • Mayoría tardía: los que incorporan la innovación cuando ya no es innovadora. Son los adversos al riesgo. Cuando más del 50% adoptó una idea, empieza a ser más riesgoso no adoptarla. Es muy probable que haya aparecido competencia. Nuestra tarea es mostrar que somos la opción más segura y trabajar en optimizar los procesos operativos (por ejemplo, tener costos bajos).
  • Rezagados: lo reticentes. Es un mercado relativamente chico, difícil de alcanzar y con poco margen.

viernes, 30 de octubre de 2015

Intro a TDD en formato autoaprendizaje

Les comparto un material que he usado un par de veces para difudir TDD en forma de autoaprendizaje o con relativamente poco soporte por parte del facilitador.

Motivación

Hace un tiempo facilitamos con Pablo Tortorella un Hackathon en el Instituto ORT de Almagro. Durante el diseño del evento (con gente de ORT como Damian Rosenfeld, Alejandro Jait y otros), surgió el interés que los asistentes, en su mayoría alumnos del Instituto, pudieran aprender algo nuevo, si no les entusiasmaba ninguno de los proyectos, o como una forma de alternar el foco.
Para eso requeríamos un material de aprendizaje autónomo.

Material

El material que contruimos es un poster en tamaño A3 que incluye una descripción de un ejercicio a realizar, un gráfico de el ciclo de TDD, y algunas consideraciones del por qué del TDD.
También referenciamos a videos cortos (de 5 min) en los que Martín Salias explica como hacer un 'hola mundo' de TDD en Java, .Net, y Python.




Feedback!

Si lo usas y encotras algo para mejorar, por favor me comentas.