lunes, 1 de abril de 2013

doctest, Usando la documentación para testear.



Me encontré con este framework de python y la verdad que quede sorprendido, su facilidad de uso y pragmatismo. La idea es que cuando realizamos funciones debemos documentarlas, que no mejor que luego de documentarla dejar un ejemplo de como funciona y el resultado que devuelve la función. Bueno la idea de este framework es utilizar esta documentación para testear nuestra función.

Veamos un ejemplo:

"""
This is the "example" module.

The example module supplies one function, factorial().  For example,

>>> factorial(5)
120
"""

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(30)
    265252859812191058636308480000000
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    >>> factorial(30.1)
    Traceback (most recent call last):
        ...
    ValueError: n must be exact integer
    >>> factorial(30.0)
    265252859812191058636308480000000

    It must also not be ridiculously large:
    >>> factorial(1e100)
    Traceback (most recent call last):
        ...
    OverflowError: n too large
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result


if __name__ == "__main__":
    import doctest
    doctest.testmod()

Como vemos en el ejemplo se creo una funcion factorial y se la documento con ejemplos de uso, luego al final de la función se indico que si se corre este modulo como programa principal, se corran los test. Por lo tanto si hacemos:

python example.py -v

La "-v" es para que doctest devuelva una salida. Con la ejecución de esta linea de código se correrán los ejemplos de la documentación devolviendo los siguientes valores:


Trying:
    factorial(5)
Expecting:
    120
ok
Trying:
    [factorial(n) for n in range(6)]
Expecting:
    [1, 1, 2, 6, 24, 120]
ok


Es genial!! Me parece una gran idea, que mal que no lo haya conocido antes. Existe un port para java que se llama doctestj; tendremos que probarlo.

Dejo link:
http://docs.python.org/3.3/library/doctest.html
https://code.google.com/p/doctestj/