Translate

miércoles, 9 de marzo de 2016

JUnit para hacer pruebas unitarias desde Java a Javascript!

Introducción

 Cuando tenemos sistemas grandes para comprobar que nuestro código realice lo mínimo de las tareas necesarias correctamente es buena idea usar las pruebas unitarias y pruebas de integración a la aplicación. Una librería muy popular y fácil de usar es JUnit ya que nos permite hacer métodos para probar funcionalidades concretas de nuestro código Java. Desafortunadamente, resulta difícil probar de forma automatizada los códigos Javascript que se usan en aplicaciones empresariales de Java, en esta ocasión se presenta un enfoque sencillo para proveer esta funcionalidad en nuestras pruebas de JUnit que ya tengamos.

Prerequisitos


  1. Java 6 o superior
  2. JUnit

Explicación


Usaremos la Java Scripting API que está disponible desde Java 6 para ejecutar código javascript dentro de Java, teniendo en cuenta que existen algunas limitaciones:

  1. Los objetos de Window no se pueden llamar (tales objetos incluyen por ejemplo console y alert entre otros).
  2. No se puede hacer manipulación del DOM, sino que debe ser javascript en su más pura esencia.
En base a estas limitaciones, el uso con JUnit se limitará a probar funciones muy específicas en vez de códigos extensos.

Algunos ejemplos

Hola mundo del scripting API

En este ejemplo comprobamos simplemente que si hay un objeto lo podamos obtener desde Java.

public class PruebasJavascript{
@Test
    public final void testJavascript() {
        System.out.println("Probando Javascript\n===================");

        ScriptEngineManager  administrador =
                new ScriptEngineManager();
        ScriptEngine engine=administrador.getEngineByName("javascript");
        ScriptContext context = engine.getContext();
      
        String script = "'Hola mundo!'";
        try {
            String expResult = "Hola mundo";
            engine.eval(script);
            String result=writer.toString();
            //System.out.println(String.valueOf(result)+"\n");
            assertEquals(expResult, result);
        } catch (ScriptException e) {
            fail("Error");
        }
    }


Inferir salida

En este ejemplo obtenemos valores impresos por el script para inferir el resultado de la ejecución. Favor de notar que como ya se dijo antes, alert y console.log no funcionarán, por ello usamos print.

public class PruebasJavascript{
@Test
    public final void testJavascript() {
        System.out.println("Probando Javascript\n===================");

        ScriptEngineManager  administrador =
                new ScriptEngineManager();
        ScriptEngine engine=administrador.getEngineByName("javascript");
        ScriptContext context = engine.getContext();
        StringWriter writer = new StringWriter();
        context.setWriter(writer);
        String script = "print('Hola mundo!');";
        try {
            String expResult = "Hola mundo";
            engine.eval(script);
            String result=writer.toString();
            //System.out.println(String.valueOf(result)+"\n");
            assertEquals(expResult, result);
        } catch (ScriptException e) {
            fail("Error");
        }
    }


Usar un objeto de Java

A veces para las comparaciones es un poco más conveniente usar objetos de Java, ya sea para almacenar o para dar un mejor formato a la salida.

public class PruebasJavascript{
@Test
    public final void testJavascript() {
        System.out.println("Probando Javascript\n===================");

        ScriptEngineManager  administrador =
                new ScriptEngineManager();
        ScriptEngine engine=administrador.getEngineByName("javascript");
        ScriptContext context = engine.getContext();

        engine.put("out", System.out);
        String script = "out.println('Hello, world!');";
            engine.eval(script);
    }

Comprobar la existencia de la API

Adicionalmente, podemos incluso hacer una prueba para verificar que podamos ejecutar las pruebas unitarias que involucren Javascript.

 @Test
    public final void testScriptAPI() {
        boolean soportaJavasCript = false;
        ScriptEngineManager mgr = new ScriptEngineManager();
        List<ScriptEngineFactory> factories = mgr.getEngineFactories();
        for ( ScriptEngineFactory factory : factories ) {
            System.out.println("ScriptEngineFactory Info");
            String engName = factory.getEngineName();
            String engVersion = factory.getEngineVersion();
            String langName = factory.getLanguageName();
            String langVersion = factory.getLanguageVersion();
            System.out
                    .printf("\tScript Engine: %s (%s)\n", engName, engVersion);
            List<String> engNames = factory.getNames();
            for ( String name : engNames ) {
                System.out.printf("\tEngine Alias: %s\n", name);
            }
            System.out.printf("\tLanguage: %s (%s)\n", langName, langVersion);
            if (langName.equalsIgnoreCase("ECMAScript")) {
                soportaJavasCript = true;
                break;
            }
        }
        assertEquals(soportaJavasCript, true);
    }

Llamar funciones ( por fin! ) 

Ahora un ejemplo un poco más real... comprobemos el resultado de una función si le mandamos ciertos argumentos.
@Test
    public final void testEcho() {
        System.out
                .println("Probando función de intentos en Javascript\n===================");

        ScriptEngineManager administrador = new ScriptEngineManager();
        ScriptEngine engine = administrador.getEngineByName("javascript");
        ScriptContext context = engine.getContext();
        // Versión simplificada de index.jsp
        String script = "function echo(message) {return message;}";
        try {
            engine.eval(script);
            Invocable invocableEngine = (Invocable) engine;

            String expResult = "Hola";
            String result =
                    String.valueOf(invocableEngine.invokeFunction("echo",
                            "Hola"));
             System.out.println(String.valueOf(result)+"\n");
            assertEquals(expResult, result);

        } catch (ScriptException e) {
            fail("Error" + e);
        } catch (NoSuchMethodException nse) {
            fail("Error" + nse);
        }
    }

 Enlaces y Recursos


5 things you didn't know about ... the Java Scripting API

Scripting for the Java Platform

No hay comentarios:

Publicar un comentario