miércoles, 24 de febrero de 2016

Unit Testing in Javascript Visual Studio 2015

Hoy hablaremos de unit testing y veremos algunas herramientas que nos pueden ayudar en proyectos javascript. El articulo es un poco extenso se podría decir que os comparto mis apuntes sobre este tema y de paso explico como me lo he montado para implantar testing en proyectos javascript usando el IDE Visual Studio 2015. Antes de hablar de herramientas y ver ejemplos sobre como integrarlas en nuestros proyectos javascript me veo obligado a hablar de unit testing, consideraciones previas, beneficios, etc. Si ya conoces la teoría y quieres info sobre como integrar diferentes herramientas de unit testing para proyectos javascript en Visual Studio 2015. ves directo al caso práctico.

Un poco de teoría


El proposito que se persigue con unit testing es tener herramientas que testeen nuestra aplicación en busca de errores o comportamientos no deseados. Un test unitario consiste en testear las funcionalidades de una clase, objeto o componente. Generalmente todos en algun momento hemos trabajado en sitios y proyectos donde no hay testeo unitario. Es fácil (aunque cada vez menos) encontrarte escenarios donde se considere que el testing unitario es un coste que no aporta demasiado, que complica y hace encarecer el proyecto. La madurez y la experiencia de haber estado en proyectos que se han descontrolado me hacen dar la razón a todos aquellos defensores del unit testing y técnicas como TDD (Test driven development) o como BDD (Bevahiour Driven Development). En este post no entraré en detalle a explicar todas las técnicas de testing ni como aplicarlas en parte porque ya hay post y libros dedicados a estos escritos por la gente que realmente sabe de la materia...

Es fácil pensar en testing como un tiempo que inviertes al final del proyecto para automatizar tests de las funcionalidades importantes. Por norma general esto es un grave error. Es complicado implantar una solución de testing en un proyecto que no ha sido diseñado pensando en que todas las funciones de los objetos, clases y componentes han de ser testeables. Has de tener en cuenta que no podrás testear de manera eficiente y fácil un diseño acoplado donde unos objetos dependen de otros directamente, donde hay clases que no tienen un proposito claro, funciones que cubren más de una funcionalidad, etc.

Por tanto ya veis que pensar en una solución testeable te obliga a realizar un ejercicio previo a la implementación y tener claro el propósito de cada componente desde el inicio. Esto podría incrementar el coste inicial para desarrollar un proyecto, es evidente, pero en proyectos de largo recorrido evitarás que se descontrole y tengas un proyecto donde soluciones una cosa y se “rompan” otras siete. A nivel de costes no sólo acabarás recuperando la inversión inicial sino que está demostrado que acabarás ahorrando mucho en la fase de mantenimiento y evolución. Seguramente hayas oido hablar sobre TDD/BDD… estas técnicas consisten en implementar los test previo al desarrollo de los componentes (simplificando muchísimo). Por tanto tendremos tests que fallan y a medida que se desarrollan los componentes empezarán a superarse los test.

Qué beneficios te podrían aportar las técnicas:
  • Te asegura que sólo escribes código para cubrir las funcionalidades demandadas.
  • Te asegura que el código funciona correctamente y hace lo que esperamos que haga en todo momento.
  • Facilita el trabajo en equipo y el mantenimiento del código.

Ya para acabar con la teoría es importante hablar sobre como enfocar un test. Un test unitario sólo debe testear la lógica de un componente, por tanto, si el componente trabaja con datos de un servicio remoto se suele simular accesos al servicio usando mocks de modo que la comunicación con terceros e infrastuctura suele quedar fuera del ámbito de testeo unitario. Otro concepto que no hemos tocado es el coverage o cobertura de los test. Imagina que tienes una función con un if / else, los valores que le pasas al test hacen que siempre pase por el If y nunca por el else… En este caso habrás creado un unit test que aporta un 50 % de cobertura sobre esa funcionalidad.

¿Debo entonces optar por tdd o bdd, siempre debería buscar el 100 % de coverage?

Entiendo que no existe una verdad absoluta, podria interesarte una estrategia u otra en función del proyecto, equipo que participa, recursos, timmings, etc. Depende con quien hables te dirá que si tdd o bdd o que busca como objetivo un 70% de coverage, etc. Lo que nadie te dirá es que no cree en automatizaciones de test. Os dejo algunos hangouts interesantes donde referentes debaten sobre estos temas.

HangOuts

Testing javascript en Visual Studio 2015


Vamos ya con la parte práctica. Como comentábamos vamos a integrar una solución de testing unitario en un proyecto javascript (da igual si usas angular o react o jquery o javascript ‘nativo’) en tu IDE Visual Studio 2015..

Necesitaremos las siguientes herramientas:
  • Framework para desarrollar lost test unitarios: JasmineJS / Mocha / (…)
  • Herramienta que permita governar los test unitarios y se encargue de ejecutarlos-> Chutzpah / Karma / Protactor
  • Herramienta para determinar la cobertura de tus tests. -> Chutzpah / Instanbul / Karma-coverage
  • Gestor de tareas que permita automatizar la ejecución de test en procesos como una build. -> Grunt / Gulp.

Para ver estos ejemplos partiremos de un proyecto javascript de tipo Apache Cordova en Visual Studio 2015.. Si no tienes la template de cordova instalada puedes seguir los pasos en un proyecto web.

Ya veis que hay frameworks y opciones como para escoger. Como framework para crear los test usaré JasmineJS.

Como test runner me decanto por Chutpah dado que se integra bien con el IDE, permite ejecutar los test desde Test Explorer de Visual Studio, te facilita integración con herramientas de ALM Microsoft y es muy sencillo de configurar no hace falta gestor de tareas (grunt o gulp). Como alternativa valoro positivamente Karma. ProtactorJS no hace mala pinta pero se basa en Selenium y requiere instalar el jdk de java y como hay que decantarse por uno esto de momento haría que lo descarte en ámbito VS.

Os paso un par de videos de Channel9 que explican paso a paso como configurar Chutzpah y como configurar karma en Visual Studio 2015..

Respecto al video de Karma en mi caso, prefiero usar Grunt que también está soportado por Visual Studio. Ambos son automatizadores de tareas de ámbito cliente.

Otro tema que veo mejorable sobre como está planteado en el vídeo es que Karma lo hace correr en Chrome y por tanto siempre necesitas tener una ventana con el navegador abierto… esto se podría evitar con PhantomJS que veremos también.

Preparación del entorno, descarga paquetes y configuración


Karma:

Os recomiendo descargar este packete de nuget que ya añade a packages.json las dependencias que necesitaremos, crea los ficheros de configuración de Karma y grunt por nosotros y la carpeta donde ubicar los test del proyecto (podrías cambiar la ruta si lo deseas).

Chutzpah:

Has de seguir los pasos del video que consisten en instalar 2 extensiones, la configuración podría decirse que es más sencilla que el caso anterior debido a que no necesitas Grunt o Gulp.

Crear un compontente testeable


No seré original y usaré el clásico componente de una calculadora con 4 casos de uso muy marcados que son sumar, restar, multiplicar y dividir. Creo un nuevo archivo javascript y lo dejo en una carpeta [root]/services.
function Calculator() {

}

Calculator.prototype.Add = Add;
Calculator.prototype.Substract = Substract;
Calculator.prototype.Divide = Divide;
Calculator.prototype.Multiply = Multiply;

function Add(a, b) {
    return a + b;
}

function Substract(a, b) {
    return a - b;
}

function Divide(a, b) {
    return a / b;
}

function Multiply(a, b) {
    return a * b;
}

Crear test unitario


Ya podemos crear nuestro primer test para el componente calculadora. Creamos un nuevo archivo javascript en la carpeta DefaultTest que llamaremos CalculatorTest. Ahora entra en juego el primer framework de los que hemos descargado JasmineJS. Un test unitario para las 4 funcionalidades de la calculadora tendría esta pinta usando Jasmine:
describe("Calculator Test", function () { 
    var calculator;
    beforeEach(function () {
        calculator = new Calculator();
    });

    it("can add", function () {
        expect(calculator.Add(5, 5)).toEqual(10);
    });

    it("can substract", function () {
        expect(calculator.Substract(10, 5)).toEqual(5);
    });

    it("can divide", function () {
        expect(calculator.Divide(10, 2)).toEqual(5);
    });

    it("can multiply", function () {
        expect(calculator.Multiply(10, 5)).toEqual(50);
    });
});

Ejecutar los tests


Chuztpah se instala como una extensión de Visual Studio. Esta extensión añade un adaptador que busca archivos de test en la solución y los muestra en el test explorer de Visual Studio. Por tanto si instalas Chutzpa en tu Visual Studio podrías governar los tests también desde la herramienta de Visual Studio aunque uses Karma como test runner. Para activar el test Explorer has de ir a Test/Windows/Text Explorer de Visual Studio 2015.


En el caso de Karma podemos lanzarlo también desde el Task Run Explorer (View/Other Windows/Task Run Explorer) y veremos el resultado en el output console de javascript. Para ello nos vamos a Task Explorer, veremos las tareas configuradas en grunt o gulp y si pulsamos botón derecho sobre una podemos ejecutarla. En la pestaña Output veremos el resultado de la ejecución de los test.



Determinar el coverage de mis test


Karma:

Si os fijáis entre los packages que hemos descargado tenemos karma-coverage. Este paquete también conocido como istanbul nos permite generar un informe con la cobertura de los test. Para ello tendremos que configurarlo en karma.conf.js, al volver a ejectura un test veremos que nos genera un fichero html en la ruta que si lo abrimos con el navegador veremos tiene esta pinta.



Chutzpah:

Al instalar el la extensión Context menu extensión de Chutzpah podemos situarnos en el solution explorer y sobre la carpeta donde hemos creado los test unitarios pulsar botón derecho y seleccionamos la opción "Run Chutzpah with coverege".



Esto lanza los test de la solución y al finalizar abre en un ventana del explorador un informe de coverage que tiene esta pinta.



Hasta aquí el post de hoy de areaTIC, me ha gustado ver que el gran Visual Studio soporta bien la integración con herramientas de testing javascript.

No hay comentarios:

Publicar un comentario