furniture
Inflatable Water Slide

¡Practica!

February 18th, 2009

Hoy me ha venido a la mente una frase de Lasse Koskela por dos razones:

  1. Los chicos de Agile Spain mencionaban en un hilo del foro del libro de Koskela (”Test Driven -Practical TDD and Acceptance TDD for Java Developers“) en el cual me escribió como dedicatoria la frase a la que me refiero.
  2. Estoy preparando un curso de TDD para mis compañeros en Malasia y en una de las pocas transparancias que hay en el curso (es un curso muy práctico) quiero plasmar la misma idea con otras palabras.

La frase (traducida del inglés) es la siguiente:

Recuerda que el aprendizaje viene con la acción.
Aprender sólo con la lectura es un oxímoron.

Diría que lo mismo se aplica a muchas otras cosas donde, si bien dominar la teoría es muy importante, el no practicar equivale más o menos a perder el tiempo.

Hablando de TDD en particular. No hay cursos, entrenadores o libros que valgan si no se practica. Y eso sólo lo puede hacer uno mismo con esfuerzo y paciencia. Está claro que todo lo anterior ayuda, y mucho, pero al final la responsabilidad de hacerlo y aprenderlo recae en uno mismo y en el esfuerzo que se ponga en ello.

Quizá sea una reflexión obvia, pero me apetecia escribirlo.

Presentación desarrollo del software para no informáticos

February 8th, 2009

Os cuelgo una presentación sobre ingeniería informática y desarrollo de software que hice hace unos meses para una audiencia no informática que se dedica a programar. Hablo de bastantes temas pero desde un punto de vista muy divulgativo y poco profundo. El formato es un pptx (lo siento :-P ).

La distribuyo bajo licencia licencia y se puede descargar aquí. Si alguien quiere utilizarla con propósitos comerciales que se ponga en contacto conmigo.

El índice de la presentación es el siguiente:

  1. Ingeniería del Software y Metodologías
    1. La problemática de la construcción de software
    2. La ingeniería del software como solución
    3. Partes fundamentales de la ingeniería del software
    4. Ciclos de vida de construcción de software
  2. Arquitectura de aplicaciones
    1. Componentes de un sistema
    2. Evolución y tipos de arquitecturas
    3. Patrones de diseño
  3. Metodologías
    1. Por qué las metodologías tradicionales no son suficiente
    2. Metodologías ágiles
    3. TDD
  4. Entornos y herramientas
    1. Entornos de desarrollo
    2. IDEs
    3. Plugins e integración de herramientas
  5. Buenas prácticas
    1. Buenas prácticas generales
    2. Particularidades del software científico
    3. Checkpoints
  6. Programación paralela
    1. Qué es la programación paralela
    2. Conceptos y clasificaciones
    3. Programación paralela
    4. Qué ayudas tiene el programador
  7. Asincronía y colas
    1. Sincronía vs asincronía
    2. Sistemas de colas
  8. Midiendo
    1. Debugging
    2. Logging
    3. Profiling
    4. Benchmarking
  9. Definición de flujos

Tagged: Agile, calidad, ingeniería del software, Presentación, TDD

Cobertura con NetBeans y Hudson

February 7th, 2009

Este artículo como PDF.

Introducción

Una vez tenemos montado un entorno TDD, y si efectivamente estamos trabajando con esta orientación, nuestro proyecto empezará a acumular tests unitarios con JUnit o cualquier otro framework lo que permitirá a nuestro servidor de integración (Hudson) utilizarlos como tests de regresión.

Si estamos siendo estrictos en la aplicación de una metodología TDD, en principio el grado de cobertura del código (el porcentaje de líneas de código que son evaluadas por un test) debería estar cerca del 100% por aquello del “ escribe primero el test y luego el código que lo supera”. Sin embargo bien porque seamos principiantes aplicando la metodología o bien porque escribamos los tests como parte del proceso de calidad en una metodología diferente, puede resultar muy complicado calcular el grado de cobertura mediante técnicas manuales. Incluso en un entorno TDD maduro, la propia complejidad del software puede complicar extraer esta información. Es por ello que se han desarrollado una serie de frameworks y herramientas que permiten automatizar este proceso.

Como decía, no estamos solos ante el peligro y tenemos herramientas diversas y con todo tipo de licencias. Por citar algunas: Clover, EMMA, VectorCAST o Cobertura. Mi elección en este caso será la última por varios motivos: es un producto open source (por los que tengo debilidad, especialmente cuando uno es autónomo), ofrece tasks para usarlo desde Ant y tiene plugins para Hudson. Es una lástima que no tenga un plugin nativo para NetBeans, aunque como el IDE nos permite ejecutar targets de Ant fácilmente, se lo podemos perdonar.

Por cierto, existe un plugin de análisis de cobertura de código para NetBeans. No he jugado mucho con él, pero parece que es un servicio que sólo puede activarse para proyectos de JSE y no está disponible, por ejemplo, para un proyecto web. Si alguien tiene experiencia con el mismo, se agradecerá el feedback.

Gran parte de la información necesaria que he usado para escribir esta entrada la he obtenido de este post .

Configurar Cobertura en el NetBeans

El proceso es sencillo:

  1. descargar el software,

  2. instalarlo,

  3. modificar el build.xml del NetBeans.

Así pues, lo primero que tenemos que hacer es descargarnos el software desde SourceForge. Nosotros vamos a contentarnos con la versión binaria y dejaremos el hacking para otro momento. A continuación procederemos a la instalación que no es más que descomprimirlo en una carpeta de la máquina de desarrollo. Yo tengo la costumbre de instalar estas cosas en el directorio /srv y además suelo crear un enlace simbólico (que será el que referencie desde los proyectos) que no incluya el número de versión para que cada vez que haga una actualización no tenga que recorrer todos los scripts para corregir la referencia.

root@hargon:/srv# tar -zxf cobertura-1.9.1-bin.tar.gz
root@hargon:/srv# ln -s cobertura-1.9.1 cobertura
root@hargon:/srv# ls -alh total 684K
drwxr-xr-x  7 root      root    4,0K 2009-02-07 13:42 .
drwxr-xr-x 21 root      root    4,0K 2009-02-07 11:23 ..
lrwxrwxrwx  1 root      root      15 2009-02-07 13:42 cobertura -> cobertura-1.9.1
drwxr-xr-x  4 root      root    4,0K 2009-02-04 21:23 cobertura-1.9.1
-rw-r--r--  1 root      root    649K 2009-02-04 21:40 cobertura-1.9.1-bin.tar.gz
root@hargon:/srv# rm cobertura-1.9.1-bin.tar.gz

Como ya he explicado en alguna ocasión, NetBeans usa scripts de Ant para realizar todas sus tareas y están modularizados de manera que podamos introducir nuestros propios targets y personalizaciones. En particular el fichero que podemos “tocar” tranquilamente es el build.xml que está en la raíz del proyecto así que, mientras no diga lo contrario, todos los fragmentos de código deberán picarse en este fichero.

Lo primero que tendremos que hacer proporcionar a Ant los diferentes tasks proporcionados por Cobertura.

<path id="cobertura.classpath">
    <fileset dir="${cobertura.dir}">
        <include name="cobertura.jar" />
        <include name="lib/**/*.jar" />
    </fileset>
</path>

<taskdef classpathref="cobertura.classpath"
    resource="tasks.properties" />

Esto es uso estándar de Ant. La ruta a la raíz del frameworks lo indicamos en la propiedad cobertura.dir que a su vez cargamos del fichero de propiedades privadas. Usamos el fichero de propiedades privadas (nbproject/private/private.properties) porque la ruta del framework tiene sentido que pueda ser diferente en las máquinas de desarrollo y en el servidor de integración y, recordemos, si tenemos bien montado el repositorio de código el directorio nbproject/private no suele incluirse en el mismo. Para que todo esto funcione deberemos cargar desde el build.xml directamente dicho fichero de propiedades:

<property file="nbproject/private/private.properties"/>

y efectivamente añadir la propiedad en nbproject/private/private.properties :

cobertura.dir=/srv/cobertura

Los pasos para usar Cobertura son los siguientes:

  1. instrumentalizar el código bajo testing,

  2. ejecutar los tests unitarios con JUnit que genera los datos de cobertura y

  3. parsear los datos de cobertura para generar informes.

Instrumentalizar el código

Cobertura (y la mayoría de de frameworks de este tipo) funciona de manera que al ejecutar los tests unitarios se analiza qué parte de las clases bajo testing están siendo accedidas por las pruebas y qué partes no y se vuelca esta información en un archivo. Para que el framework de testing (en nuestro caso JUnit) pueda obtener esta información, Cobertura habrá tenido que instrumentalizar previamente las clases bajo test. Es decir, antes de ejecutar los tests, habremos tenido que permitir a Cobertura que genere un bytecode modificado (instrumentalizado) para cada una de las clases bajo testing. Es un proceso similar a como funcionan algunos profilers . Para obtener las clases instrumentalizadas lo haremos de la siguiente manera:

<target name="cobertura-instrument" depends="compile">
    <cobertura-instrument
        todir="${cobertura.classes.dir}"
        datafile="${cobertura.ser.file}" >

    <fileset dir="${build.classes.dir}">
        <include name="**/*.class"/>
    </fileset>
    </cobertura-instrument>
</target>

Creo que el target se entiende bastante fácilmente: básicamente estamos especificando donde guardaremos las las clases instrumentalizadas ( cobertura.classes.dir ), en qué fichero se escribirán los datos de cobertura ( cobertura.ser.file ) y dónde residen las clases a instrumentalizar ( build.classes.dir ). Esta última propiedad es una de las propiedades estándar que residen en el nbproject/properties ; las otras dos deberemos introducirlas en dicho fichero.

cobertura.ser.file=${build.dir}/cobertura.ser
cobertura.classes.dir=${build.dir}/cobertura/classes

Como nuestro target requiere los bytecode de las clases a instrumentalizar tiene como dependencia el target estándar compile que es el que usa NetBeans para compilar el proyecto. Entre las dependencias del propio compile se encuentra el target init que, entre otras cosas, es el encargado de cargar el fichero de propiedades (y por eso nosotros no tenemos que hacer de manera explícita la carga del mismo).

Ejecutar los tests

El siguiente paso consiste en ejecutar los tests sobre las clases instrumentalizadas para así extraer la información de cobertura. Aquí también podemos aprovecharnos de los scripts generados por NetBeans. Nuestro nuevo target , que llamaremos test-cobertura básicamente será una copia del target test (que es el que normalmente usa NetBeans para ejecutar las diferentes tests unitarios) con pequeñas modificaciones. Esta es la pinta que debería tener:

<target name="cobertura-test"
    depends="set-cobertura-file, init,compile-test,
    -pre-test-run,cobertura-instrument,
    -do-test-run,test-report,-post-test-run,-test-browse">
</target>

Con respecto al original, hemos añadido dos nuevas dependencias. Por un lado cobertura-instrument que es una referencia al target anterior para asegurarnos que existen las clases instrumentalizadas. Por otro lado hemos definido otra dependencia a otro target que también debemos construir y que muestro a continuación:

<target name="set-cobertura-file" depends="init">
    <property
        name="test-sys-prop.net.sourceforge.cobertura.datafile"
        value="${cobertura.ser.file}"/>
</target>

Este target es necesario para establecer un parámetro de sistema que debemos pasar a todos los tasks de JUnit usados en los diferentes targets de los ficheros de scripting incluidos desde el build.xml (en particular el build-impl.xml ). Necesitamos pasar este parámetro para que los tasks del JUnit sepan dónde escribir la información de cobertura mientras ejecuta los tests.

El nombre de la propiedad de sistema a pasar es net.sourceforge.cobertura.datafile el porqué se pasa el parámetro de sistema en una propiedad con un nombre algo diferente, lo tengo explicado en este otro post . El valor de la propiedad, como ya hemos visto (pues es un propiedad que ya he necesitado en targets anteriores), está dentro del fichero nbproject/project.properties y por eso nuestro target tiene una dependencia del target init que es el que se encargaba de cargar las propiedades definidas en ese fichero.

Falta un detalle adicional: especificar al JUnit que ejecute las clases instrumentalizadas y no las generadas directamente en la fase de compilación. Para hacer esto sólo tenemos que introducir unos pequeños cambios en el classpath utilizado por los targets de testing lo que implica cambiar la propiedad run.test.classpath definida en el nbproject/project.properties para que quede así:

run.test.classpath=\
    ${cobertura.dir}/cobertura.jar:\
    ${cobertura.classes.dir}:\
    ${javac.test.classpath}:\
    ${build.test.classes.dir}

Si hemos hecho todo correctamente al ejecutar el target cobertura-test deberían ejecutarse los tests unitarios como siempre pero además debería haberse construido el fichero build/cobertura.ser que contiene la información de cobertura.

Crear los informes de cobertura

El fichero build/cobertura.ser , como decíamos, contiene la información de cobertura pero está en formato binario porque ha tenido que generase en tiempo de ejecución de los tests de manera eficiente. Para extraer información legible hay que parsear dicho fichero. Para ello Cobertura nos proporciona el task cobertura-report .

Este task permite generar los informes en dos formatos: en XML o en HTML . Nosotros generaremos ambos. El primero lo necesitaremos para pasárselo al plugin correspondiente en el Hudson. El segundo nos proporcionará una vista agradable y legible. Veamos el target que tenemos que definir:

<target name="cobertura-report" depends="cobertura-test">
    <cobertura-report
        datafile="${cobertura.ser.file}"
        format="xml"
        destdir="${cobertura.report.dir}"
        srcdir="${src.dir}" />

    <cobertura-report
        datafile="${cobertura.ser.file}"
        format="html"
        destdir="${cobertura.report.dir}"
        srcdir="${src.dir}" />
</target>

Creo que aquí no hay mucho que explicar. Defino dónde está el fichero que contiene la información de cobertura, dónde quiero generar los informes y el formato de los mismos. Como siempre habremos de definir la propiedad cobertura.report.dir en el nbproject/project.properties :

reports.dir=${build.dir}/reports
cobertura.report.dir=${reports.dir}/cobertura-report

Si ahora ejecutamos este target deberían generarse los informes en el directorio especificado. Si le echamos un ojo a los informes de tipo HTML vemos que básicamente ha generado unas páginas al estilo de la documentación de las API pero con la información de cobertura. Una manera muy útil e intuitiva de mostrar la información.

Configurar el Hudson

Una vez hemos configurado todo lo anterior, ya tenemos hecho el trabajo duro. La configuración del Hudson, afortunadamente, es bastante sencilla. Estos son los pasos:

  1. instalar Cobertura,

  2. instalar el plugin de Cobertura y

  3. configurar el job :

    1. configurar el workspace para indicar dónde está Cobertura,

    2. añadir el cobertura-report en la lista de targets que tiene que ejecutar el Ant y

    3. configurar el directorio donde están los informes en XML

Instalar Cobertura

Para que el Ant lanzado por Hudson al construir el proyecto sea capaz de instanciar los tasks del Cobertura, éste tendrá que ser instalado en la máquina donde reside Hudson. El proceso de instalación será exactamente análogo al que hemos hecho en el entorno de desarrollo: descargar el paquete, descomprimirlo en el directorio /srv y establecer un enlace simbólico.

Instalar el plugin

Una vez tenemos Hudson instalado, añadir plugins es trivial. Desde la interfaz web vamos a Hudson -> Manage Hudson -> Manage Plugins -> Available y entonces seleccionamos Hudson Cobertura plugin y le damos a Install . El asistente entonces instala el plugin tras los cual habrá que reiniciar Hudson.

Configurar eljob

Aquí estamos presuponiendo que ya existe un job previo correctamente configurado y al que simplemente vamos a añadir el soporte de cobertura. Si no fuera así, echadle un ojo a este otro post que ya publiqué en su momento.

Lo primero que haremos es configurar el workspace para que sea capaz de encontrar Cobertura durante la fase de construcción del proyecto. Para ello, nos vamos al directorio nbproject/private/private.properties del job correspondiente y añadimos la propiedad que indica dicha ruta:

cobertura.dir=/srv/cobertura

A continuación modificaremos los targets de Ant que usa Hudson para construir el job . Si tuviéramos el target test lo eliminaríamos y a continuación añadiremos el target cobertura-report .

Lo siguiente es configurar el plugin para que utilice el informe XML generado:

  • Publish Cobertura Coverage Report : activamos la opción para que Hudson muestre la información de cobertura.

    • Cobertura xml report pattern : build/reports/cobertura-report/coverage.xml
      Aquí ponemos la ruta al fichero donde hemos generado el informe en formato XML.

    • Coverage Metric Targets : este apartado nos permite definir las métricas a partir de las cuales la construcción del job se considera estable o no.


En principio ya está todo. Ahora podríamos lanzar una construcción para comprobarlo. Si todo va bien, Hudson mostrará los informes de cobertura bajo el enlace Coverage Report en la raíz del job .

- 8 -


Tagged: Agile, calidad, Hudson, Java, NetBeans, TDD

Monitorizar Hudson desde NetBeans

February 6th, 2009

En un post anterior explicaba como montar un entorno básico para poder empezar a trabajar en un entorno TDD. El ide que elegí fue NetBeans y el servidor de integración continua Hudson. El siguiente paso natural es poder monitorizar Hudson desde el propio NetBeans sin tener que abrir el navegador web. Para poder llevar a cabo esta tarea, existe un plugin desarrollado por el propio equipo de Hudson. Aunque su uso es muy sencillo, en este post explicaré cómo instalarlo, configurarlo y utilizarlo. Los desarrolladores del plugin tienen un entrada en su wiki, así que mi post es un poco redundante :-P

Instalar el plugin

El primer paso consiste en instalar el plugin. Para ello tenemos varias alternativas.

Podemos descargarlo desde el NetBeans Plugin Portal como un fichero nbm que luego instalaremos a través del gestor de plugins del NetBeans: Tools -> Plugins -> Downloaded -> Add Plugins y seleccionaremos el fichero descargado.

La otra alternativa, que prefiero, es hacerlo directamente desde la pestaña de plugins disponibles siempre que tengamos configurado el Update Center del Plugin Portal : Tools -> Plugins -> Available Plugins -> Install .

Configurar el plugin

Una vez instalado lo tenemos disponible en la pestaña Services junto con los servidores, los SGBDs y demás, valga la redundancia, servicios.

Haciendo click derecho sobre el icono del Hudson, nos aparece la opción de añadir una instancia (podríamos monitorizar simultáneamente diferentes servidores de integración). Simplemente tendremos que completar el asistente dándole un nombre a esa instancia, asignándole la url donde reside el servidor y una frecuencia de refresco del estado del mismo.

Usar el plugin

A partir de ese momento podemos ver el estado de Hudson de un vistazo. Por un lado podemos ver el estado de todos los jobs con códigos de colores (correcto, roto o inestable) y el estado de ocupación de la cola de construcción. Por otro lado podemos programar nuevas construcciones de cualquier job haciendo click derecho sobre el job -> Start job o ver una información más extendida del job haciendo doble click sobre el mismo (lo que abre una ventana en el panel del editor). Obviamente podemos saltar directamente a la página web correspondiente en el navegador haciendo click derecho sobre el nodo correspondiente -> Open in Browser .

netbeans_service_hudson1

El “problema” de monitorizar de esta manera es que nos fuerza a acceder a la pantalla de servicios. Afortunadamente el plugin también proporciona una alerta a manera de iconito rojo parpadeante y estresante en el margen inferior izquierdo del NetBeans. El icono omnipresente persiste hasta que se arregle el job roto. Clickando sobre el mismo nos da información del job (o jobs ) que están causando la alerta.

Disfrutadlo.


Tagged: Hudson, NetBeans, TDD
-->