Primeros pasos con Cucumber-JVM

Hace poco más de dos meses estoy trabajando casi cotidianamente con Cucumber-JVM y como consecuencia de ello he aprendido muchísimo sobre dicha herramienta. Si bien ya tenía bastante experiencia con la implementación Cucumber-Ruby, resulta que la implementación Java tiene sus particularidades.

Para compartir lo que he ido aprendiendo he decidido grabar una serie de videos. He aquí el primero de ellos: Introducción a Cucumber-JVM, espero les resulte útil.

 

Agile no es para todo ni todos (Open Space UY 2014)

Continuando con el relato de este evento, la segunda sesión en la que participé me resultó especialmente interesante. No recuerdo el nombre de la persona que la propuso, pero la idea era analizar algunas situaciones debatiendo cómo enfrentarlas desde los métodos ágiles. Las tres situaciones planteadas fueron:

  1. Cliente ausente
  2. Cambio de prioridades constantemente en un proyecto Scrum
  3. Miembro de equipo mala onda/desmotivado y riesgo de contagio al resto del equipo

(si bien mi descripción es sólo de una línea, en la sesión se dió un poco más de detalle sobre cada una)
Una vez planteadas las situaciones empezamos a hacer una especie de brainstorming sobre posibles estrategias para afrontarlas. Para ponerle un poquito de picante a la sesión, pedí la palabra y sin pelos en la lengua dí «mi dictamen»:

Cliente ausente => no uses métodos ágiles

Agile no es para todo,  Agile no es una bala de plata y tampoco se puede aplicar siempre, hay casos en los que no se puede o no conviene usar agile. Puede que suene muy fuerte pero la experiencia me ha demostrado que para aplicar agile deben darse ciertas condiciones de las cuales tal vez la más importante sea el involucramiento del cliente. Si tu cliente está ausente, seguramente sea mejor utilizar un proceso más tradicional, con especificaciones detalladas, entrevistas formales de relevamiento y documentos firmados. O incluso tal vez sea mejor no hacer el proyecto (si es que esta opción está disponible). Si, suena extremo pero es como suelo manejarme y estoy contento.

Cambio de prioridades contastemente => Kanban

Si trabajas con Scrum y no logras «congelar» los requerimientos del Sprint backlog podrías en primer lugar intentar trabajar con iteraciones más cortas. Si eso no es posible o no funciona, entonces tal vez no debas usar Scrum sino hay más del estilo Kanban.

Miembro de equipo mala onda/desmotivado => agile no es para todos

No tengo una solución para esto, supongo que habría que consultar a un coach «humano», yo estoy más del lado técnico. Lo que sí tengo en claro es que Agile no es para todo el mundo. Me gusta hacer la analogía entre Agile y la forma de juego del Barcelona. Si tienes un equipo con las características del Barcelona, puedes intentar jugar como el Barcelona y posiblemente obtengas buenos resultados, pero si no tienes un equipo así, tal vez debas buscar otra forma de juego. Con agile pasa lo mismo, si tienes un equipo autoorganizado, motivado y un proyecto agile-friendly, seguramente puedas aplicar agile y obtener buenos resultados, pero si tu equipo no es capaz de autoorganizarse y tu gente no está motivada, entonces tal vez sea mejor probar con otro cosa. Claro, si hablas con un «consultor agile», difícilmente te diga esto. Al contrario, el «consultor agile» muy probablemente te proponga intentar transformar tu equipo. ¿Es posible tal transformación? Supongo que sí. ¿es fácil? Me parece que no. Pero de algo estoy convencido: si tal transformación es posible, es con el acompañamiento de un coach/consultor ágil.

Open Space UY 2014, sesiones primera parte

La primera sesión a la que asistí fue propuesta por @danilomerlino y trató sobre testing. En realidad inicialmente fue planteada como gestión de bugs, pero una vez expuesta la problemática, nos la pasamos hablando del testing. Estimo que en la sesión fuimos unas 15 personas. En forma resumida la problemática que disparó la sesión fue: a pesar de que los programadores hacen sus pruebas unitarias, cuando el software llega a los testers estos encuentran una gran cantidad defectos. Entre las sugerencias habladas para superar esta situación se mencionaron diversas prácticas como ser:

  1. Pair programming / Revisión de pares
  2. Test cruzados entre los programadores
  3. Trabajo más cercano entre programadores y testers
  4. Behaviour-Driven Development

Algunos de los asistentes comentaron haber experimentado bajas en la cantidad de defectos reportados a partir del uso de 1,2 y 3, cosa que también ha sido confirmada por diversos autores (Steve McConell entre ellos).

Yo fui quien hizo la propuesta 3 y junto con la propuesta mostré algunos features de proyectos en los que he participado en el último tiempo. Hay que destacar que si bien esta práctica permite generar pruebas de aceptación automatizadas, esto es simplemente un efecto colateral, el gran beneficio que  genera usar BDD es la charla que se da entre el equipo y el usuario  y los ejemplos de uso resultantes de la misma.

Comparto a continuación algunos links mencionados durante la sesión que pueden resultar de interés:

 

Continuará…

 

Open Space UY 2014

Ayer estuve participando de un Open Space organizado por la comunidad ágil de Uruguay. El mismo se llevó a cabo en las instalaciones de la Universidad Católica de Uruguay.

La logística fue impecable, las instalaciones de la universidad resultaron muy adecuadas y el evento contó con varios sponsors lo que permitió contar con almuerzo y coffe breaks a pesar de tratarse de un evento gratuito.

Luego de unas palabras iniciales de Ariel (@scrumjedi), la facilitación del marketplace estuvo a cargo de @pablolis y el facilitación del cierre estuvo a cargo Martín Mari.

No tengo el número exacto de sesiones, pero había 4 slots horarios y unas cinco salas, por lo que estimo que debe haber habido unas 20 sesiones.

Gracias AgileUY, fue un gran evento y lo disfruté muchísimo.

PD: en los próximos días voy estar posteando sobre las sesiones en las que participé.

 

Más reflexiones sobre docencia universitaria

En 2011 cuando tomé a mi cargo la materia Elementos de Ingeniería de software en UNQ tuve que decidir cómo estructurar las clases de la materia. Por reglamento la materia tenía (y tiene) una carga horaria de 6 horas semanales de clase. Hasta ese momento la materia se dictaba en dos clases semanales, si mal no recuerdo una clase de 2 horas y otra de 4. Luego de una charla con las autoridades mis opciones eran:

  • Mantener un esquema de 2 clases semanales, ya sea de una de 2 y otra de 4 o un esquema más tradicional de 2 clases de 3 horas cada una.
  •  Cambiar a un esquema «maratónico» de una sola clase semanal de 6 horas

Una vez más el dilema: ¿comodidad del docente o «mejor aprendizaje» de los alumnos?  Quien me conoce sabe claramente que elegí la primer opción: dos clases semanales de 3 horas cada una. En parte porque dictar una clase de 6 horas me parece insalubre tanto para los alumnos como para el docente. Por otro lado estoy convencido que el aprendizaje tiene naturalmente una estructura iterativa y en ese sentido el tener más clases permite realizar más iteraciones lo cual representa más ciclos de feedback y por ende más oportunidades de mejora/aprendizaje.

¿y si la materia fuera de 4 horas semanales? Una clase de 4 horas parece bastante razonable. Si, definitivamente es más razonable, pero aún así hubiera elegido dos clases semanales pues el argumento iterativo sigue aplicando en este caso también.

 

Reflexiones sobre docencia universitaria

En 2009 participé como docente del curso experimental de Algoritmos y Programación 1 a cargo de Rosita Wachenchauzer en FIUBA. Esa experiencia me hizo un click y me llevó a replantearme varias cuestiones respecto de la forma de organizar las clases. Quiero en este artículo enfocarme en una de las cuestiones que generó ese click.

Tradicionalmente las clases de Algoritmos y Programación en FIUBA se dividen en dos clases semanales: una clase teórica dictada generalmente por el profesor a cargo de la materia y una clase práctica a cargo de los docente auxiliares. En algo3 lo hacemos así. Una de las particularidades del curso de Algoritmos y Programación 1 de Rosita era (y aún hoy lo es pues el curso sigue dictandose) la organización de las clases. La materia se dicta 2 días por semana y cada día se dicta teoría y práctica. Esto permite que el alumno vea un tema en la clase teórica y a continuación lo lleve a la práctica justamente en la clase práctica. Personalmente creo que este enfoque es mejor para facilitar el aprendizaje que el enfoque tradicional.

Para los docentes esta diferencia en la organización de las clases puede tener un impacto operativo importante, sobre todo para los docentes de dedicación simple que no asisten a la universidad todos los días. Con el enfoque tradicional cada docente asiste a la universidad una sola vez por semana: el profesor asiste un día a dictar la clase teórica y los auxiliares asisten otro dia a dictar la clase práctica. El enfoque alternativo implica que todos los docentes asistan dos veces por semana a la universidad ya que cada dia se dicta teoría y práctica.

Si tomamos como verdadera la hipótesis que de que este segundo enfoque es mejor para facilitar el aprendizaje de los alumnos, nos surge entonces un dilema como docentes: ¿qué priorizar a la hora de organizar las clases: ¿la comodidad del docente o el mejor aprendizaje del alumno?

Continuará…

#! crunchbang, un linux para probar

Hace un tiempo mi colega DiegoS me mencionó esta distribución y finalmente la semana pasada decidí armar una VM para probarla.

Me gustó, es una distribución basada en Debian con gestor de ventanas OpenBox y tengo la sensación de que es más liviano que Mint (el otro linux que suelo utilizar).

Una particularidad que me resultó muy interesante es que viene con un conjunto de shortcuts que permiten prescindir del mouse para muchas de las operaciones cotidianas.

Cómo enseñamos TDD

TDD es una práctica cuyo punto clave es la secuencia de pasos que se siguen para obtener la solución. En Algo3 explicamos la teoría y luego la ponemos en práctica haciendo dojos en las clases. También les damos ejercicios a los alumnos y les pedimos que los resuelven haciendo TDD, pero la realidad es no tenemos forma de asegurarnos que hayan arribado a la solución usando TDD. Hay algunas situaciones observables que pueden sugerir que la solución no fue generada utilizando TDD (por ejemplo si la solución tiene baja cobertura es muy posible que no se haya utilizado TDD o al menos no se lo haya utilizado correctamente o todo el tiempo). Al mismo tiempo todos los ejercicios de programación que resolvemos en clase procuramos hacerlo usando TDD. Finalmente evaluamos su conocimiento sobre TDD con alguna pregunta en el examen. Creo que es un enfoque bastante integral y razonable para el contexto de la materia, donde es común que tengamos más de 40 alumnos por curso. Pero es posible que haya mejores enfoque para otros contextos.

Sin ir más a lejos, yo mismo en UNQ estrené este cuatrimestre un enfoque distinto. Cabe aclarar que el contexto de UNQ es distinto, en primer lugar es una materia de ingeniería de software donde se supone que los alumnos ya vieron algo de TDD. Al mismo tiempo, la cantidad de alumnos es mucho menor, suelen ser alrededor de 10. Finalmente la dinámica de la materia es distinta: no tenemos separación explícita entre teoría y práctica y tampoco tenemos exámenes formales. Lo que hacemos (o mejor dicho lo que hemos hecho este cuatrimestre) es explicar TDD haciendo TDD, de una, explicando la teoría sobre la misma práctica. Luego les damos a los alumnos algunas katas para resolver y les pedimos que graben un screencast mientras van resolviendo la kata. Esto nos permite observar cómo los alumnos aplican la técnica paso a paso y detectar si algo no fue correctamente entendido.

Implementación de Step Definitions en Cucumber-JVM

Continuando con los dilemas del uso de cucumber, luego de un par de reuniones con los analistas/testers del proyecto, tomamos algunas decisiones:

  • Escribir los steps con las menor cantidad de parámetros posibles
  • Agrupar los step definitions en base a conceptos de negocio
  • Utilitzar Step definitions con estado (stateful)

A partir de esto, el flujo de trabajo es: los analistas/testers identifican los casos de tests y los expresan como escenarios usando lenguaje Gherkin. Luego usando las anotaciones de Cucumber-JVM yo genero los métodos que implementan los pasos de los escenarios. Estos métodos son los que se conocen como «Step definitions». Hasta aquí llega la herramienta. La forma en que se implementan los Step Definitions depende de cómo sea la aplicación que se pretende testear. Si quisiéramos testear una aplicación web, posiblemente usariamos el driver de Selenium. En mi caso, tengo que testear un sistema de facturación a través de una interfaz propietaria basada en mensajes XML. Más allá de la interfaz hay dos cuestiones que requieren interactuar directamente con la base de datos del sistema:

  1. Limpiar los datos luego de la ejecución de cada test
  2. Realizar ciertas verificaciones (asserts) sobre los datos generados por el sistema que no se encuentran disponibles en la interfaz

Para lidiar con todas estas cuestiones he generado un conjunto de clases (¿micro-framework?) que agrupan código común y que me permiten elevar un poco el nivel de abstracción. cucumber_domain   Scenario, no es una clase, es un caso de prueba especificado en lenguaje Gherkin en un archivo de extensión .feature (un feature suele contener varios scenarios). StepsDefinition no es una clase, sino que son métodos agrupados en clases según criterios de negocio. BusinessAction, son clases que agrupan operaciones de alto nivel con granularidad de negocio. ScenarioContext, es un singleton donde se almacena el estado a lo largo de la ejecución de los distintos steps que conforman un scenario. Este contexto es reseteado cada vez que se ejecuta un scenario. Driver, es una clase con operaciones «de bajo nivel» que permite la interacción con el sistema que se está testeando. DBHelper, es una clase con operaciones para interactuar con la base de datos, se utiliza para resetear el estado del sistema y también para realizar algunas verificaciones que no pueden hacer utilizando el driver/api. Los siguientes diagramas muestran la interacción de estos componentes. cucumber_sequence1     cucumber_sequence2

La polémica: TDD está muerto

Recientemente David Heinemeier Hansson, creador del framework Rails, publicó un artículo titulado TDD is dead, long live testing que causó cierto debate con referentes de la disciplina. Incluso Uncle Bob y Kent Beck dedicaron incluso algunas líneas a la cuestión.

Personalmente creo que TDD es una práctica muy útil, la uso a menudo, pero no todo el tiempo ni para todo. Me gusta y suelo usar  TDD cuando tengo que escribir lógica negocio. Generalmente no uso TDD cuando tengo que escribir lógica de presentación y cosas por el estilo.

Lo que destaco de este intercambio de opiniones es que me ha dado material para trabajar con mis alumnos :-).