[Python-es] ¿Algún recurso sobre trucos prácticos y ejemplos realistas de testing?

Jesus Cea jcea en jcea.es
Mar Dic 31 10:06:39 CET 2013


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Una cosa que he ido descubriendo con los años es que para poder hacer
buenos tests es conveniente que lo que estés probando se preste a
ello. Tienes que programar de forma que lo que haces sea fácilmente
testable.

El enfoque habitual en otros lenguajes, y mi tendencia en el pasado es
utilizar inyección de dependencias. De hecho hubo una época en la que
di la lata un poco para incluir inyección de dependencias en Python,
pero la respuesta masiva fue que eso era antipitónico y que el futuro
eran los mocks y similares.

Pero me encuentro que para probar una rutina de 20 lineas escribo 200
lineas de tests más complejos que la propia rutina a comprobar, el
desarrollo es lento y no puedo evitar pensar que estoy haciendo algo
mal :-).

Así que, ¿alguien conoce recursos online con consejos prácticos y
ejemplos realistas?. Porque hacer un chequeo mínimamente completo de
esta rutina está siendo un infierno.

Esta rutina genera una clave al azar e intenta registrarla en un
servidor, que devuelve un 401 mientras un administrador no ha admitido
el registro (y en ese caso devuelve un 200). Una vez que tenemos el
200, nos guardamos ese usuario y clave en disco y no necesitamos
repetir la operación.

"""
def consigue_autenticacion() :
    # Creamos el fichero si es preciso
    open("/tmp/heartbeat", "w").close()
    #os.utime("/tmp/heartbeat")

    try :
        with open("/local/auth", "r") as f :
            token = f.read().strip()
        if " " in token :
            return  # Ya tenemos usuario y clave
    except FileNotFoundError :
        with open("/dev/urandom", "rb") as f :
            token = f.read(4096)
        if len(token) != 4096 :
            raise RuntimeError("Lectura parcial de entropía")
        token = md5(token).hexdigest()
        with open("/local/auth", "w") as f :
            f.write(token+"\n")

    usuario = "XXXXXX"
    clave = "XXXXXXXX"  # Confidencial, pero no crítico
    auth = requests.auth.HTTPBasicAuth(usuario, clave)

    addr = netifaces.ifaddresses("eth0")
    ip_addr = addr[netifaces.AF_INET][0]["addr"]
    mac_addr = addr[netifaces.AF_LINK][0]["addr"]
    mac_addr = mac_addr[0:2]+mac_addr[3:5]+mac_addr[6:8]+ \
                mac_addr[9:11]+mac_addr[12:14]+mac_addr[15:17]

    factor = 1*60
    while True :
        t = time.time()
        respuesta = requests.get("https://XXXXXX.jcea.es/registro?"
                "ip_addr=%s&mac_addr=%s&ts=%.0f" \
                        %(ip_addr, mac_addr, time.time()),
             auth = auth,
             verify = "XXXXXXXXX.jcea.es.cert",
             timeout = 1*60,
             headers = {"clave": token})
        os.utime("/tmp/heartbeat")
        if respuesta.status_code == 401 :
            t = t + factor
            factor = factor * 3
            if factor > 3600 :
                factor = 3600
            while time.time() < t :
                time.sleep(10)
                os.utime("/tmp/heartbeat")
            continue  # Volvemos a intentarlo
        elif respuesta.status_code == 200 :
            with open("/local/auth", "w") as f :
                f.write(mac_addr+" "+token+"\n")
            return
        else :
            raise RuntimeError("El servidor nos devuelve un status %s" \
                    %respuesta.status_code)
"""

El código de testeo de esta rutina es complicado de cojones, feo,
frágil. Uso Mocks para comprobar que las llamadas se realizan en el
orden y con los parámetros correctos, tiro excepciones, simulo
ficheros, etc. La pruebo a fondo. Pero desarrollar el test ha sido
costosísimo.

¿Consejos?.

Se admiten recomendaciones de libros.

- -- 
Jesús Cea Avión                         _/_/      _/_/_/        _/_/_/
jcea en jcea.es - http://www.jcea.es/     _/_/    _/_/  _/_/    _/_/  _/_/
Twitter: @jcea                        _/_/    _/_/          _/_/_/_/_/
jabber / xmpp:jcea en jabber.org  _/_/  _/_/    _/_/          _/_/  _/_/
"Things are not so easy"      _/_/  _/_/    _/_/  _/_/    _/_/  _/_/
"My name is Dump, Core Dump"   _/_/_/        _/_/_/      _/_/  _/_/
"El amor es poner tu felicidad en la felicidad de otro" - Leibniz
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.15 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQCVAwUBUsKJG5lgi5GaxT1NAQLu7wQAlG+qzPwUIZWi0wLtgXBg44WWMbODuqZd
SQrsSxFxEL5GHhyWiW2RCJ7cG5B9Sgtbfg2Sez0o9PiAwFxMku42DxTJwS/tPTpK
15I9WUuvN2lylAOvMPvn5CuUsuis2wQ0R2hv5jgXPJ39Kl/e2ncwuiZB83J1APvd
5jZXkbYoTz8=
=9H+8
-----END PGP SIGNATURE-----


Más información sobre la lista de distribución Python-es