Ejercicio: interpretación de métricas de test y cobertura

Amo las métricas, creo que es un efecto colateral de la búsqueda de la mejora continua. Para mejorar es necesario medir, pero con medir no basta, hay que saber qué medir y luego hay que interpretar lo medido para poder accionar al respecto.

Hoy quiero compartir un actividad que hicimos esta semana con mis alumnos de Ingeniería de software en UNTreF. La dinámica fue simple, dado un proyecto tomamos los gráficos de evolución de tests y cobertura generados por Jenkins y los analizamos para generar hipótesis a partir de ellos. Invito a los lectores a sumarse a este ejercicio, analicen los gráficos e intenten extraer información de ellos. Comparto un poco de contexto que les puede resultar útil para el análisis: el proyecto en cuestión es un modelo (o sea pura lógica, sin UI ni base de datos), los desarrolladores son alumnos universitarios que tenían que trabajar con 2 consignas:

  1. Hacer el desarrollo usando TDD
  2. Hacer integración commiteando al repositorio central (en el mainline) luego de cada nuevo test verde.
  3. Si el build se rompe, se para la línea hasta que sea arreglado

analisis_1

Aquí va mi análisis y con mis hipótesis/conclusiones (=>):

  • En el build #10 se agregaron 10 tests => no respetaron la consigna 2
  • Pero a pesar del agregado de tests la cobertura disminuyó => posiblemente por el agregado de código de dominio sin los correspondientes tests => violación de la consigna 1
  • En los siguientes builds (#11,#12 y #13) la cantidad de test aumenta de a uno y también se evidencia un aumento en la cobertura.
  • En los builds #14 y #15 se evidencian nuevamente saltos grandes en la cantidad de tests y de la mano de ello también un aumento de la cobertura.
  • Entre los builds #15 y #18 la cantidad de tests se mantiene constante y lo mismo ocurre con la cobertura => esto podría indicar pasos de refactoring.
  • En el build #19 disminuye la cantidad de tests y con ello la cobertura => esto podría deberse a un cambio en el código de dominio que no fue acompañado completamente por la correspondiente actualización de test.
  • Finalmente la cantidad de tests se mantiene constante en los últimos builds pero la cobertura disminuye => me hace pensar en agregado de código sin los correspondientes tests.

¿algo que agregar?

Automatización de pruebas en AS400

Hace un par de semanas comencé a trabajar un proyecto con @dfontde y @CodeRaguet para automatizar pruebas de una aplicación AS400/RPG. Nunca en mi mi vida había hecho nada con esa tecnología y creo que justamente ese fue un factor clave para que decida involucrarme en el proyecto.

Nuestro primer día de trabajo, uno de los programadores de la aplicación en cuestión nos hizo un breve tour introductorio a la plataforma AS400, al lenguaje RPG y a la aplicación sobre la cual debemos trabajar.

Dadas las particularidades de la plataforma y de cómo está construida la aplicación, decidimos tomar un enfoque de caja negra. Básicamente vamos a intercambiar mensajes con la aplicación via una cola. De esta forma nuestras pruebas se reducen a correr un setup (el cual hay que codear en RPG), escribir un mensaje en una cola, leer la respuesta de otra cola y verificar dicha respuesta. Todo esto lo vamos a codear en Java, que si bien no es “el sueño del pibe”, me resulta bastante más amistoso que RPG.

Hicimos una primer prueba de concepto exitosa para entender la interacción Java/PC <-> RPG/AS400. En este momento estamos analizando la herramienta de especificación de pruebas para lo cual estamos haciendo una prueba de concepto con FitNesse.

Continuará…

Cursos en la previa de Agiles 2015

Como de costumbre en la previa de Agiles 2015 habrá un conjunto de cursos organizados de forma independiente. En ese contexto estaré dictando en Montevideo mi Taller de Continuous Delivery y Prueba automatizada.

El términos generales el taller está divido en 2 partes. La primera enfocada en los conceptos centrales de la práctica de Continuous Delivery y un conjunto de técnicas y herramientas para su implementación que incluyen Jenkins, Puppet y Docker. La segunda se enfoca en la automatización de pruebas, lo cual constituye un punto fundamental en toda estrategia de Continuous Delivery. En esta segunda parte veremos herramientas tales como JUnit, Cucumber-JVM y FitNesse. Si bien el taller tiene una base conceptual independiente de toda tecnología, la parte práctica de automatización de pruebas se realiza con Java.

Los detalles de logística e inscripción están disponibles en la página de Evolución Ágil.

Selección de herramientas de prueba (parte 2)

En la primera entrega de esta serie presenté una arquitectura de prueba de referencia. En esta entrega voy a instanciar esa arquitectura de referencia en Ruby.

Comenzado por las pruebas del programador (unitarias y de componentes), tendremos que nuestro objeto de prueba serán clases programadas en Ruby. Para hacer este tipo de pruebas una de las herramientas más populares es RSpec la cual nos daría una arquitectura de pruebas conformada por:

  • Lenguaje de especificación: Lenguaje de Dominio Específico provisto por RSpec
  • Intérprete: es el propio RSpec
  • Driver: dado que estamos testeando clases Ruby, que estamos haciendo pruebas unitarias y de componentes y que RSpec está hecho en Ruby no requerimos de ningún driver particular. En todo caso nuestro driver es el mismo Ruby
  • Librería de aserciones: es el mismo RSpec
  • Motor de ejecución: RSpec

Un detalle a tener presente es que este tipo de pruebas son pruebas que hace el programador para sí mismo, ya sea para guiar el desarrollo (si está haciendo TDD) o bien para garantizar que sus clases se comportan acorde a lo esperado. Este tipo de pruebas no suelen interesar al usuario, pues son de índole técnica y al mismo tiempo mucho más granulares que las funcionalidades pedidas por el usuario.

arquitectura_developer_tests_ruby

 

 

Pasando ahora a las pruebas de aceptación funcionales, si bien podríamos utilizar el mismo set de herramientas, la realidad es que esperamos que el usuario esté involucrado y por ello usaremos un set distinto de herramientas de cara tener un lenguaje de especificación más “amistoso” para el usuario. Al mismo tiempo el objeto de nuestras pruebas ya no son clases sino la aplicación como un todo:

  • Lenguaje de especificación: Gherkin
  • Intérprete: Cucumber
  • Driver: dependerá de la forma en que pretendamos comunicarnos con la aplicación. Suponiendo que nos comunicamos via HTTP, podríamos utilizar Capybara en conjunto con WebDriver de Selenium.
  • Librería de aserciones: RSpec
  • Motor de ejecución: Cucumber

arquitectura_user_tests_ruby

 

Selección de herramientas de prueba (parte 1)

Una de las decisiones a tomar al querer hacer pruebas automatizadas es qué herramientas utilizar. Para poder tomar esta decisión resulta importante entender mínimamente la arquitectura de una infraestructura de pruebas automatizadas. El siguiente gráfico resumen de forma muy general una arquitectura de modelo para esta problemática.

arq_pruebasSi bien el gráfico puede sugerir una arquitectura de capas, la misma rara vez se cumple a nivel de implementación pero si es cierto que para elemento representa un nivel de abstracción distinto en la estructura de la solución.

En el nivel de abstracción de más alto tenemos un lenguaje de especificación que nos permite expresar la prueba.
Un ejemplo de un lenguaje posible de especificación podría ser Gherkin.

En un segundo nivel tenemos un intérprete de ese lenguaje
que nos permitirá relacionar la especificación abstracta con fragmentos de código que escribiremos nosotros y que comúnmente se denominan “glue code”.
Para el caso Gherkin tenemos como intérpretes las familia de herramientas Cucumber, en particular si quisieras escribir nuestro código en Java podríamos utilizar Cucumber-JVM.

En el tercer nivel tendremos un componente que denominamos **driver** que nos permitirá interactuar con nuestra aplicación. Lo que hace el driver en concreto es implementar el protocolo de comunicación necesario para interactuar con el sistema bajo prueba.
Siguiendo con el ejemplo anterior y asumiendo que el sistema bajo prueba es de tipo web, podríamos entonces utilizar Selenium Web Driver el ofrece una implementación en Java.

El siguiente elemento de nuestra arquitectura es la librería de aserciones, la cual nos permitirá precisamente hacer aserciones sobre el resultado de las operaciones realizadas sobre el sistema bajo prueba.
En este caso es común utilizar alguna librería de la familia xUnit. En el caso de Java utilizaríamos JUnit.

Finalmente, como último ítem de esta enumeración tenemos un motor de ejecución que se encarga de instanciar y ejecutar los elementos previamente mencionados.
En este caso una alternativa muy común en el mundo Java en particular es utilizar el mismísimo JUnit.

En la segunda parte de este artículo ofreceré algunos ejemplos concretos de implementación de esta arquitectura.

Fin del taller de prueba automatizada

El jueves pasado tuvimos el quinto y último encuentro del taller de prueba automatizada que dictamos junto con Pablo Tobia en FIUBA. El taller era abierto y gratuito pero con inscripción previa. Justamente al ser totalmente gratuito implicaba cierto riesgo en lo que hace a la planificación, pues es común que mucha gente se inscriba y luego no asista. Para mitigar esto, pedimos a todos los interesados que para confirmar su vacante resolvieran un pequeño ejercicio de programación.

Inicialmente tuvimos unas 40 personas que manifestaron interés en participar del taller cuando aún no estaba definido el horario. Una vez que definimos el horario le informamos a estas ~40 personas y les pedimos que resolvieran el ejercicio para completar su inscripción. Sólo 12 de los 40 lo hicieron. Y aún así, de esos 12 solo 10 participaron del taller.

El taller consistió en 5 encuentros de  ~3 horas. Como guía del taller utilizamos los cuadrantes de testing de Marrick con lo cual el contenido quedó organizado de la siguiente forma:

  • Encuentro #1: conceptos básicos de testing y presentación del enfoque de los cuadrantes
  • Encuentro #2:
    • foco en el cuadrante #1 (support programming & technology facing),
    • test automation manifest
    • xUnit test patterns
    • Test doubles
    • Coverage
  • Encuentro #3 y #4:
    • foco en el cuadrante #2 (support programming & business facing)
    • tipos de herramientas para automatización de pruebas
    • arquitectura de las herramientas de automatización de pruebas
    • testing de aplicaciones tipo enterprise
    • SeleniumIDE, Cucumber, Fitnesse
    • Phantom, Slimer and CasperJS
    • Watir & PageObjects
  • Encuentro #5:
    • foco en los cuadrantes #3 y #4 (test que critican el producto)
    • Stress testing, JMeter
    • AB testing
    • Calidad del software más allá del testing
    • Testing en distintos tipos de proceso de desarrollo
    • El rol de tester

Tanto docentes como alumnos quedamos muy contentos con el taller y concluimos que perfectamente podria ser una materia de las carreras de informática de FIUBA (en realidad es posible que también aplique a otras carreras pero sabemos que en FIUBA estos temas no estan cubiertos por ninguna materia en la actualidad). En caso querer convertir este taller en un materia (o en un curso más amplio) deberíamos agregar temas talles como: planificación de la prueba, definición y administración de casos de prueba, herramientas de soporte, Testlink, modelos de calidad, etc.

Finalmente quiero agradecer a todos los que participaron este experimento para mi ha sido un gran placer el tiempo compartido.

Clasificación de herramientas para automatizar pruebas de funcionales

Las pruebas funcionales son las que típicamente hace un tester, que más le importa al usuario y sería ideal definir en conjunto con él, pues estas pruebas interactúan con el SUT desde la perspectiva del usuario. Son pruebas que Marrick clasifica como Business Facing.

Para este tipo de pruebas es muy relevante la forma en que las herramientas permiten expresar la prueba, ya que dado que son “pruebas de usuario”, dependiendo de la forma en este planteado el proyecto podríamos querer que estas pruebas sean escritas por el usuario.
En este sentido es que las herramientas para automatizar este tipo de pruebas han adoptado distintos enfoques:

  • Record and Play: permiten “grabar” la interacción del usuario con el SUT para luego reproducirlo. Con este tipo de herramienta, básicamente se ejecuta manualmente 1 una vez cada caso de prueba mientras la herramienta va grabando la interacción de manera que la misma y una completada la grabación las pruebas pueden repetirse tantas veces como se guste de forma automática. Un ejemplo de este tipo de herramientas es SeleniumIDE.
  • Keywork-Driven: este tipo de herramientas permiten definir las pruebas utilizando un conjunto de palabras claves par estructurar la prueba. Luego es necesario escribir cierto código (glue code) para vincular la prueba (expresada con palabras claves específicas) y el SUT. En esta categoría de herramientas entra toda la familia de Cucumber.
  • Data-Driven: este tipo de herramientas permiten especificar la prueba a partir de condiciones expresadas en tablas. Cada tabla es interpretada por por cierto código (glue code) que permite la interacción con el SUT. Las herramientas de la familia Fitnesse entran en este grupo.

Si bien muchas veces las herramientas pueden utilizarse de diversas formas, en general suelen ser concebidas para ser utilizadas de una forma particular (una silla es concebida para sentarse, sin embargo en ocasiones es posible utilizarla para elevar nuestra altura como si fuera una escalera). En este sentido cada herramienta puede verse más orientada con alguno de los grupos mencionados, pero ello no quita que la podamos usar de forma distinta.

Automatización de pruebas: principios, prácticas y herramientas

Finalmente, me hice un rato y mandé mi propuesta de sesión sobre este tema a Agiles 2014. Para quienes gusten darme feedback, pueden ver la propuesta completa en el sistema de call for papers de la conferencia.

Una cuestión que no está mencionada en la propuesta es qué fue lo que me llevó a proponer una sesión sobre este tema.

Como programador y sobre todo desde que me metí en el mundo Smalltalk, las pruebas unitarias automatizadas se volvieron un artefacto imprescindible en mi trabajo. Al ser Smalltalk un lenguaje de tipado dinámico no contaba con la (falsa) seguridad que proveen los compiladores en los lenguajes de tipado estático. Por esto me sentía obligado a escribir pruebas unitarias automatizadas para tener cierto nivel de seguridad de que no estaba rompiendo mi proyecto. Tiempo más tarde cuando comencé a trabajar en la implementación de la práctica de continuous delivery tomé conciencia de que con automatizar las pruebas unitarias y de componentes no era suficiente. Fue en ese momento que comencé a meterme gradualmente en las cuestiones de automatización de pruebas de aceptación de usuario. En ese sentido trabajé con Juan Gabardini en preparar un curso de automatización de pruebas y tiempo después comencé a trabajar con Pablo Tobia (alto tester) en el armado de una materia de testing que finalmente materializamos en el curso que dictamos en FIUBA. Al mismo tiempo para ganar más experiencia de campo logré meterme a trabajar como Software Engineer in Test en un proyecto de automatización de pruebas de un sistema de facturación. Todo esto me ayudó a ganar experiencia e incorporar muchísimo conocimiento sobre esta temática.

Como de costumbre, si la sesión es aceptada en Ágiles 2014, intentaré hacer una prueba previa en uno de los encuentros de la comunidad ágile@BsAs, mm, en realidad creo que la prueba lo voy a hacer igual más allá de que sesión sea aceptada en Agiles 2014 o no.

Taller (experimental) de Testing

Hace varios de meses comenzamos a trabajar con mi colega Pablo Tobia en el armado de la un materia de Testing. Leímos, experimentamos, debatimos, hablamos con otros colegas y finalmente decidimos pasar a la acción: vamos a dictar un Taller de testing. El objetivo central de este taller es obtener feedback de lo que hemos armado para poder refinarlo de cara a presentarlo formalmente como una materia. A continuación comparto un poco más de información en forma de “Preguntas frecuentes” para los posibles interesados.

¿Qué duración tiene? Son 4 clases de 3 horas cada una. Adicionalmente al tiempo de clase se espera que los alumnos dediquen cierto tiempo (entre 1 y 2 horas semanales) a la realización de algunas prácticas.

¿Qué costo tiene el curso? Ninguno, es gratuito aunque posiblemente le pidamos a los alumnos algún tipo de contraprestación como por ejemplo traer alimentos para donar a un comedor comunitario o algo por el estilo.

¿Cuando se dicta? Aún no lo tenemos del todo definido pero la idea es hacerlo durante Julio aprovechando que no hay clases. Seguramente sea un día por semana a partir de las 18 o 19 horas.

¿Da créditos para la carrera? No, el taller es absolutamente extra-curricular.

¿Qué conocimiento previo necesito? El taller es muy práctico y está orientado a la automatización, con lo cual se espera que todo alumno pueda programar. En principio trabajaremos con Java y Ruby. Si no sabes de ninguno de estos lenguajes y crees que puedes darte maña para aprenderlos, no hay problema, pero nosotros no vamos a explicar Java ni Ruby. Al mismo tiempo, son necesarios cierto conocimiento de aplicaciones web (http, html, etc) y de metodologías de desarrollo de software.

¿Cuál es el temario del curso? En forma resumida podemos decir que veremos algunas cuestiones conceptuales, varias cuestiones de índole práctica y diversas herramientas como ser Cucumber, Fit, Watir, RSpec, JUnit, CasperJS y Selenium.

¿Cómo me anoto? Si estas interesado participar, te pedimos que completes este formulario.

 

 

 

Libros de testing

Luego de la inquietud planteada sobre mi percepción del testing en la industria y la academia, me dediqué a profundizar en el tema. Por un lado conociendo herramientas y buscando oportunidades laborales relacionadas al tema y por otro lado leyendo al respecto. Comparto aquí la lista de los principales libros que he leído/consultado: