jueves, 2 de diciembre de 2010

Implementación de Asserts en GXUnit

Una función básica de cualquier herramienta xUnit es tener la posibilidad de escribir assertions. Estas funciones realizan comparaciones de resultados de ejecuciones con resultados esperados de las pruebas, indican si se obtiene lo esparado y en caso de que no se cumpla, muestra información sobre la ejecución.

Planteamos el siguiente ejemplo de utilización:
Se quiere probar un método DIV(in:&a, in:&b, out:&c) que realiza la división entre &a y &b y devuelve el resultado en &c. Realizamos las siguientes pruebas
1) DIV(1, 1) resultado esperado: 1
2) DIV(1, 0) resultado esperado: error

La idea es que la herramienta permita escribir lo siguiente:
&esperado = 1
DIV(1,1,&resultado)
AsserEquals(&resultado,&esperado)
&esperado = error
DIV(1,0,&resultado)
AsserEquals(&resultado,&esperado)

Nuestra idea es implementarlo mediante un procedimiento GX para independizarnos del ambiente en que se esté generando. La primera limitación con la que nos encontramos es que no podemos sobrecargar el método AssertEquals, o sea, llamar a AssertEquals(a,b), siendo a y b de cualquier tipo.
Para implementar estas funciones en GXUnit planteamos las siguientes opciones de diseño.

Opción 1) Generar un AssertEquals para cada tipo. Por Ejemplo: AssertNumericEquals, AssertStringEquals, etc. Además pasar un parametro más de tipo Boolean que indicará si la función genera un error/excepción.
El pseudocódigo quedaría:

&esperado = 1
DIV(1,1,&resultado)
AssertNumericEquals(&resultado,&esperado,&error)


Opción 2) Generar un AssertEquals que se le pase siempre un string y un tipo, y la herramienta convierta el string al tipo correcto. Para esta opción el usuario debería convertir sus variables a string antes de usar la función Assert por lo que no quedaría para nada práctico.


Nos parece que la primera opción es la más práctica e intuitiva de usar, pero estamos abiertos también a otras ideas. Por ejemplo alguna manera de utilizar sobrecarga de funciones utilizando external objects o alguna otra herramieta.

3 comentarios:

  1. Pero ... ¿Porqué no pueden sobrecargar el AssertEquals?

    ResponderEliminar
  2. El assert es un comando que deberia ser provisto en forma nativa por GeneXus.
    Es algo que todo lenguaje que permita testeo unitario deberia tener.
    Tambien deberia poder manejar excepciones con try/catch.

    Si esto no fuera posible, creo que me inclinaria por un Objeto Externo para cada una de las plataformas, que permita hacer el assert.

    Entiendo que hay que desarrollar el objeto externo tanto para .NET, Java y Ruby (y en el futuro puede agregarse mas plataformas), lo cual complica un poco.

    La propuesta del procedure, la dejaria como ultimo recurso.

    ResponderEliminar
  3. En un principio la idea era hacerlo como una función nativa, pero tenemos entendido que esto no se puede hacer utilizando extensiones, habría que modificar código de GeneXus.

    Otra idea era utilizando external objects pero no permite crear dos métodos de igual nombre. Cuando digo dos métodos me refiero a un assertEquals para enteros y otro para strings.

    Se agradece alguna idea de como implementar la sobrecarga.

    ResponderEliminar