unittest unitarias test pruebas modules integracion python linux unit-testing

unitarias - test en python



Modificaciones de archivo de prueba unitaria (6)

Creo que estás en el camino correcto. Dependiendo de lo que necesite hacer, chroot puede ayudarlo a configurar un entorno para sus scrpits que parezca real, pero no lo es.

Si eso no funciona, entonces podría escribir sus scripts para tomar una ruta ''raíz'' como argumento.

En una ejecución de producción, la ruta raíz es solo /. Para las pruebas, crea un entorno oculto en / tmp / test y luego ejecuta los scripts con una ruta raíz de / tmp / test.

Una tarea común en los programas en los que he estado trabajando últimamente es modificar un archivo de texto de alguna manera. (Hola, estoy en Linux. Todo es un archivo. Y administro sistemas a gran escala).

Pero el archivo que modifica el código puede no existir en mi escritorio. Y probablemente no quiera modificarlo si está en mi escritorio.

He leído acerca de las pruebas unitarias en Dive Into Python, y está bastante claro lo que quiero hacer cuando pruebo una aplicación que convierte números decimales a números romanos (el ejemplo en DintoP). La prueba es muy autónoma. No necesita verificar que el programa IMPRIMA lo correcto, solo necesita verificar que las funciones devuelven el resultado correcto a una entrada determinada.

En mi caso, sin embargo, tenemos que probar que el programa está modificando su entorno correctamente. Esto es lo que se me ocurrió:

1) Cree el archivo "original" en una ubicación estándar, quizás / tmp.

2) Ejecute la función que modifica el archivo, pasando la ruta al archivo en / tmp.

3) Verifique que el archivo en / tmp se haya cambiado correctamente; pasar / fallar prueba de la unidad en consecuencia.

Esto me parece kludgy. (Obtiene incluso más kludgier si desea verificar que las copias de seguridad del archivo se crean correctamente, etc.) ¿Alguien ha encontrado una manera mejor?


Cuando toco archivos en mi código, tiendo a preferir burlarme de la lectura y escritura real del archivo ... entonces puedo dar a mis clases los contenidos exactos que quiero en la prueba, y luego afirmar que la prueba está escribiendo de nuevo contenidos que espero.

He hecho esto en Java, y me imagino que es bastante simple en Python ... pero puede requerir diseñar tus clases / funciones de tal manera que sea FÁCIL simular el uso de un archivo real.

Para esto, puedes intentar pasar en las transmisiones y luego simplemente pasar una secuencia de entrada / salida simple que no escribirá en un archivo, o tener una función que haga "escribir esta cadena en un archivo" o "leer esto" cadena de un archivo ", y luego reemplace esa función en sus pruebas.


Es posible que desee configurar la prueba para que se ejecute dentro de una cárcel chroot, para que tenga todo el entorno que la prueba necesita, incluso si las rutas y las ubicaciones de archivos están codificadas en el código [no es una buena práctica, pero a veces se obtiene el archivo ubicaciones de otros lugares ...] y luego verifique los resultados a través del código de salida.


Tienes dos niveles de prueba.

  1. Filtrado y modificación de contenido. Estas son operaciones de "bajo nivel" que realmente no requieren E / S de archivos físicos. Estas son las pruebas, la toma de decisiones, las alternativas, etc. La "lógica" de la aplicación.

  2. Operaciones del sistema de archivos Crear, copiar, cambiar el nombre, eliminar, hacer una copia de seguridad. Lo sentimos, pero esas son operaciones adecuadas del sistema de archivos que, bueno, requieren un sistema de archivos adecuado para las pruebas.

Para este tipo de prueba, a menudo usamos un objeto "simulado". Puede diseñar una clase "FileSystemOperations" que incorpore las diversas operaciones del sistema de archivos. Usted prueba esto para asegurarse de que lee, escribe, copia, renombra, etc. básicos. No hay una lógica real en esto. Solo métodos que invocan las operaciones del sistema de archivos.

A continuación, puede crear un MockFileSystem que simula las diversas operaciones. Puedes usar este objeto Mock para probar tus otras clases.

En algunos casos, todas las operaciones de su sistema de archivos están en el módulo os. Si ese es el caso, puede crear un módulo MockOS con la versión simulada de las operaciones que realmente usa.

Coloque su módulo MockOS en PYTHONPATH y puede ocultar el módulo de SO real.

Para las operaciones de producción utiliza sus clases "lógicas" bien probadas más su clase FileSystemOperations (o el módulo de SO real).


Estás hablando de probar demasiado a la vez. Si comienza a tratar de atacar un problema de prueba diciendo "Verifiquemos que modifique su entorno correctamente", está condenado al fracaso. Los entornos tienen docenas, tal vez incluso millones de variaciones potenciales.

En cambio, mira las piezas ("unidades") de tu programa. Por ejemplo, ¿va a tener una función que determine dónde se deben escribir los archivos? ¿Cuáles son las entradas a esa función? ¿Quizás una variable de entorno, tal vez algunos valores leídos de un archivo de configuración? Pruebe esa función y no haga nada que modifique el sistema de archivos. No le pase valores "realistas", pase valores que sean fáciles de verificar. Cree un directorio temporal, setUp con archivos en el método setUp su prueba.

Luego prueba el código que escribe los archivos. Solo asegúrate de escribir los contenidos correctos del archivo de contenido. ¡Ni siquiera escribas en un sistema de archivos real! No necesita crear objetos de archivo "falsos" para esto, solo use los prácticos módulos de StringIO ; son implementaciones "reales" de la interfaz de "archivo", simplemente no son las que su programa realmente va a escribir.

En última instancia, tendrá que probar la función final de nivel superior, todo en realidad está conectada a la realidad, que pasa la variable de entorno real y el archivo de configuración real y lo ensambla todo. Pero no te preocupes por eso para comenzar. Por un lado, comenzarás a buscar trucos mientras escribes pruebas individuales para funciones más pequeñas y la creación de simulacros de prueba, falsificaciones y talones se convertirá en algo natural para ti. Por otro: incluso si no puede entender cómo probar esa llamada a una función, tendrá un alto nivel de confianza de que todo lo que está llamando funciona perfectamente. Además, notará que el desarrollo basado en pruebas lo fuerza a hacer sus API más claras y más flexibles. Por ejemplo: es mucho más fácil probar algo que llama a un método open() en un objeto que proviene de algún lugar abstracto, que probar algo que llama a os.open en una cadena que lo pasa. El método open es flexible; se puede falsificar, se puede implementar de manera diferente, pero una cadena es una cadena y os.open no le da ningún margen de maniobra para detectar qué métodos se os.open sobre ella.

También puede crear herramientas de prueba para facilitar las tareas repetitivas. Por ejemplo, twisted proporciona facilidades para crear archivos temporales para pruebas integradas directamente en su herramienta de prueba . No es raro que las herramientas de prueba o los proyectos más grandes con sus propias bibliotecas de prueba tengan una funcionalidad como esta.


Para los lectores posteriores que solo quieren una manera de probar que la escritura de código en los archivos está funcionando correctamente, aquí hay una "entrada_fácil" que parchea la versión abierta de un módulo para usar StringIO. fake_open devuelve un dict de archivos abiertos que pueden examinarse en una unidad de prueba o doctest, todo ello sin necesidad de un sistema de archivos real.

def fake_open(module): """Patch module''s `open` builtin so that it returns StringIOs instead of creating real files, which is useful for testing. Returns a dict that maps opened file names to StringIO objects.""" from contextlib import closing from StringIO import StringIO streams = {} def fakeopen(filename,mode): stream = StringIO() stream.close = lambda: None streams[filename] = stream return closing(stream) module.open = fakeopen return streams