[Python-es] ¿Algún recurso sobre trucos prácticos y ejemplos realistas de testing?
Chema Cortes
pych3m4 en gmail.com
Mar Dic 31 16:44:42 CET 2013
El día 31 de diciembre de 2013, 10:06, Jesus Cea <jcea en jcea.es> escribió:
> -----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.
Para peticiones asíncronas, el patrón que parece funcionar mejor es el
patrón "Actor". Al convesar con el resto de actores a través de
mensajes, es mucho más fácil desacoplar y testear cada parte por
separado (o sea, con "mocks" que emulan otros actores). Lo único
complicado es crear un diseño de actores que sea suficientemente
resiliente (recuperación frente a fallos). Para python hay librerías
Actor como pykka[1], parley[2] o pulsar[3], pero no las he probado
como para darte alguna idea.
Para realizar las pruebas, mírate pywovs[4] a ver si te ahorra trabajo.
[1]: http://pykka.readthedocs.org/en/latest/
[2]: http://osl.cs.uiuc.edu/parley/
[3]: http://pythonhosted.org/pulsar/
[4]: http://heynemann.github.io/pyvows/
No conozco libros que traten de estos temas para python. Mi consejo es
que te mires otros lenguajes como Scala/Akka o Erlang si piensas hacer
un sistema de actores algo más complejo.
--
Hyperreals *R "Quarks, bits y otras criaturas infinitesimales":
http://ch3m4.org/blog
Buscador Python Hispano: http://ch3m4.org/python-es
Más información sobre la lista de distribución Python-es