viernes, 8 de noviembre de 2013

TDD y los test de integración

La práctica de programación Test-driven Development (TDD), desarrollo guiado por pruebas, está basada en la iteración continua de 5 pasos:

  • Escribir una prueba para un requisito.
  • Verificar que la prueba falla.
  • Escribir la implementación más simple para cumplir el requisito.
  • Ejecutar las pruebas automatizadas.
  • Refactorizar código.


Con la repetición de estos pasos conseguimos que la aplicación que se escribe únicamente cumpla con los requisitos que nos han pedido, con lo cual vamos directo al grano, no escribimos más código del que toca, diseñamos la aplicación en el mismo momento que escribimos las pruebas y el código de la misma, el código resultante suele ser muy legible y entendible ya que el paso de refactorización ayuda precisamente a esto, conseguimos una gran cobertura, los test cubren un porcentaje altísimo del código, entre el 90 y el 100%, conseguimos descartar test que no aportan nada y por supuesto es un mecanismo crucial para detectar errores de regresión.

Esta claro que aporta mucho para poder realizar una buena aplicación, pero como todo tiene sus limitaciones, hay que recordar que la base en la práctica del TDD son los test unitarios, no  los test de integración y mucho menos los test de interfaz gráfica o funcionales, esto quiere decir que sea lo que se que estemos implementando debe poder probarse de forma unitaria, de aquí las limitaciones de TDD con aplicaciones que se integran con bases de datos, con objetos o sistemas distribuidos “externos”, o incluso con la propia interfaz gráfica de la aplicación. 

Está claro que con el uso de stubs o mock objects podemos hacer todo pero hay que plantearse si el esfuerzo que conlleva escribir un test para estos casos no es demasiado elevado, o bien si este test lo podemos suplir mediante un test de integración más sencillo de escribir.

Entonces si es muy costoso realizar un test unitario puede que el mejor camino sea realizar el test de integración directamente. Esto puede que rompa algo la filosofía de TDD pero creo que es más práctico, incluso pienso que si el test de integración se ejecuta en tiempos similares a los unitarios el uso en conjunto con la práctica de TDD es factible. Al fin y al cabo se trata de ser prácticos.

viernes, 8 de marzo de 2013

MoveScript: Plugin para Jira





Hace más o menos un año, en la empresa donde trabajo, tuvimos la necesidad de realizar cierta lógica adicional a la función move de Jira.

La función move no hace otra cosa que mover una issue de un proyecto a otro, pero puede resultar interesante que además de realizar esta funcionalidad se requiera, por ejemplo añadir un comentario, modificar el assignee o ciertos campos de la issue, etc... Por este motivo realizamos una modificación en el funcionamiento del move. Actualmente, ya conociendo la API de desarrollo de Jira mucha más, y con el objetivo de introducirme en el mundo de desarrollo de Atlassian, he realizado un plugin que permite escribir un script usando groovy que se ejecute justo después de realizar el move y teniendo la información de la issue que se esta cambiando de proyecto.

En realidad no es nada más que un listener que cuando se lanza un move ejecuta un script groovy, tengo que decir que esto no hubiera sido posible sin antes haber conocido el plugin Script Runner, que fue el que despertó mi curiosidad por el mundo groovy.

Todo aquel que necesite utilizar esta funcionalidad, puede descargar el plugin en el market de Atlassian:  Move Script 

domingo, 20 de enero de 2013

Groovy y Java - Embeded groovy

Un punto que considero muy interesante es el poder ejecutar scripts o clases groovy desde java, por este motivo he estado realizando algunas pruebas.

La primera prueba que he realizado ha sido la de ejecutar un método de una clase groovy dentro de un main de java.

En concreto he creado la clase "HelloGroovy.groovy":

package main

class HelloGroovy {
 
 
 public String getHello(){
  return "Hello from groovy class";
 }
}
Y después una clase Java que llama al método "getHello", la clase "EmbeddedGroovy.java":


package main
package main;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.io.File;

public class EmbeddedGroovy {
 
 
 public static void main(String args[])throws Exception{
  ClassLoader parent = EmbeddedGroovy.class.getClassLoader();
  GroovyClassLoader loader = new GroovyClassLoader(parent);
  Class helloGroovyClass = loader.parseClass(new File("src/main/HelloGroovy.groovy"));
  GroovyObject groovyObject = (GroovyObject) helloGroovyClass.newInstance();
  Object[] arguments = {};
  String hello = (String)groovyObject.invokeMethod("getHello", arguments);
  System.out.println(hello);
 }

}


Como se puede apreciar esta llamada es muy parecida a la que se haría si la clase en lugar de ser de tipo groovy fuera java, pero existen otras manera de invocar a scripts groovy muy interesantes por ejemplo utilizando GroovyScriptEngine, de esta manera se puede ejecutar un script groovy dentro de una clase java tal y como se muestra en el siguiente ejemplo.

Script groovy hello.groovy:

println("Hello World");

Y la clase java ExecuteGroovyScript.java:


package main;

package main;

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

public class ExecuteGroovyScript {
 
 public static void main(String args[])throws Exception{
  String[] scripts = new String[] { "src/main" };
  GroovyScriptEngine gse = new GroovyScriptEngine(scripts);
  Binding binding = new Binding();
  gse.run("hello.groovy", binding);
 }

}

Al ser totalmente interpretado dota a java de la posibilidad de modificar script groovy y afectar al programa que lo incorpora sin necesidad de compilar, es más tal y como se muestra en la página http://groovy.codehaus.org/Embedding+Groovy existe la posibilidad de pasar parámetros a los scripts.
En la página mencionada anteriormente también describe un ejemplo básico utilizando la shell de groovy.