Si está escribiendo una biblioteca o una aplicación, ¿a dónde van los archivos de prueba de la unidad?
Es bueno separar los archivos de prueba del código principal de la aplicación, pero es incómodo colocarlos en un subdirectorio de "pruebas" dentro del directorio raíz de la aplicación, porque hace que sea más difícil importar los módulos que probará.
¿Hay una mejor práctica aquí?
python
unit-testing
code-organization
Solo lectura
fuente
fuente
Respuestas:
Para un archivo
module.py
, normalmente se debe llamar a la prueba unitariatest_module.py
, siguiendo las convenciones de nomenclatura Pythonic.Hay varios lugares comúnmente aceptados para poner
test_module.py
:module.py
.../tests/test_module.py
(al mismo nivel que el directorio de código).tests/test_module.py
(un nivel bajo el directorio de código).Prefiero # 1 por su simplicidad de encontrar las pruebas e importarlas. Cualquiera sea el sistema de compilación que esté utilizando, puede configurarse fácilmente para ejecutar archivos a partir de
test_
. En realidad, el patrón predeterminadounittest
utilizado para el descubrimiento de prueba estest*.py
.fuente
Solo 1 archivo de prueba
Si solo tiene 1 archivo de prueba, se recomienda colocarlo en un directorio de nivel superior:
Ejecute la prueba en CLI
Muchos archivos de prueba
Si tiene muchos archivos de prueba, póngalo en una
tests
carpeta:Ejecute la prueba en CLI
Utilizar
unittest discovery
unittest discovery
encontrará todas las pruebas en la carpeta del paquete.Crear una carpeta
__init__.py
entests/
Ejecute la prueba en CLI
Referencia
pytest
Buenas prácticas para el diseño de pruebaunittest
Marco de prueba de la unidad
fuente
Una práctica común es colocar el directorio de pruebas en el mismo directorio principal que su módulo / paquete. Entonces, si su módulo se llamara foo.py, su diseño de directorio se vería así:
Por supuesto, no hay una sola forma de hacerlo. También puede hacer un subdirectorio de pruebas e importar el módulo usando la importación absoluta .
Donde sea que coloque sus pruebas, le recomendaría que use la nariz para ejecutarlas. Nariz busca a través de sus directorios para las pruebas. De esta manera, puede poner pruebas donde sea que tengan más sentido organizacionalmente.
fuente
Tuvimos la misma pregunta al escribir Pythoscope ( https://pypi.org/project/pythoscope/ ), que genera pruebas unitarias para los programas de Python. Encuestamos a las personas en las pruebas en la lista de Python antes de elegir un directorio, había muchas opiniones diferentes. Al final, elegimos poner un directorio de "pruebas" en el mismo directorio que el código fuente. En ese directorio generamos un archivo de prueba para cada módulo en el directorio padre.
fuente
También tiendo a poner mis pruebas unitarias en el archivo, como señala Jeremy Cantrell arriba, aunque tiendo a no poner la función de prueba en el cuerpo principal, sino poner todo en un
bloquear. Esto termina agregando documentación al archivo como 'código de ejemplo' sobre cómo usar el archivo python que está probando.
Debo agregar, tiendo a escribir módulos / clases muy ajustados. Si sus módulos requieren un gran número de pruebas, puede colocarlos en otro, pero aun así, aún agregaría:
Esto permite que cualquiera que lea su código fuente sepa dónde buscar el código de prueba.
fuente
De vez en cuando me encuentro revisando el tema de la colocación de la prueba, y cada vez la mayoría recomienda una estructura de carpetas separada al lado del código de la biblioteca, pero encuentro que cada vez los argumentos son los mismos y no son tan convincentes. Termino colocando mis módulos de prueba en algún lugar al lado de los módulos principales.
La razón principal para hacer esto es: refactorización .
Cuando muevo cosas, quiero que los módulos de prueba se muevan con el código; Es fácil perder las pruebas si están en un árbol separado. Seamos honestos, tarde o temprano terminas con una estructura de carpetas totalmente diferente, como django , flask y muchos otros. Lo cual está bien si no te importa.
La pregunta principal que debe hacerse es esta:
¿Estoy escribiendo:
Si un:
Una carpeta separada y el esfuerzo adicional para mantener su estructura pueden ser más adecuados. Nadie se quejará de que sus pruebas se implementen en producción .
Pero también es tan fácil excluir las pruebas de ser distribuidas cuando se mezclan con las carpetas principales; pon esto en setup.py :
Si b:
Puede desear, como todos nosotros, que esté escribiendo bibliotecas reutilizables, pero la mayoría de las veces su vida está ligada a la vida del proyecto. La capacidad de mantener fácilmente su proyecto debe ser una prioridad.
Luego, si hizo un buen trabajo y su módulo se adapta bien a otro proyecto, probablemente se copiará, no se bifurcará o se convertirá en una biblioteca separada, en este nuevo proyecto y se moverán las pruebas que se encuentran junto a él en la misma estructura de carpetas es fácil en comparación con pescar pruebas en un desastre en el que se había convertido una carpeta de prueba separada. (Puede argumentar que no debería ser un desastre en primer lugar, pero seamos realistas aquí).
Entonces, la elección sigue siendo suya, pero diría que con las pruebas confusas se logran las mismas cosas que con una carpeta separada, pero con menos esfuerzo para mantener las cosas ordenadas.
fuente
Utilizo un
tests/
directorio y luego importo los módulos de aplicación principales utilizando importaciones relativas. Entonces, en MyApp / tests / foo.py, podría haber:para importar el
MyApp.foo
módulo.fuente
No creo que haya una "mejor práctica" establecida.
Puse mis pruebas en otro directorio fuera del código de la aplicación. Luego agrego el directorio principal de la aplicación a sys.path (que le permite importar los módulos desde cualquier lugar) en mi script de ejecución de prueba (que también hace algunas otras cosas) antes de ejecutar todas las pruebas. De esta manera, nunca tengo que eliminar el directorio de pruebas del código principal cuando lo libero, lo que me ahorra tiempo y esfuerzo, aunque sea una cantidad muy pequeña.
fuente
os.sys.path.append(os.dirname('..'))
Desde mi experiencia en el desarrollo de marcos de prueba en Python, sugeriría colocar las pruebas unitarias de python en un directorio separado. Mantener una estructura de directorio simétrica. Esto sería útil para empaquetar solo las bibliotecas principales y no empaquetar las pruebas unitarias. A continuación se implementa a través de un diagrama esquemático.
De esta manera, cuando empaqueta estas bibliotecas utilizando un rpm, puede empacar los módulos de la biblioteca principal (solo). Esto ayuda a la mantenibilidad, particularmente en entornos ágiles.
fuente
Le recomiendo que revise algunos proyectos principales de Python en GitHub y obtenga algunas ideas.
Cuando su código se hace más grande y agrega más bibliotecas, es mejor crear una carpeta de prueba en el mismo directorio que tiene setup.py y reflejar la estructura de directorios de su proyecto para cada tipo de prueba (unittest, integración, ...)
Por ejemplo, si tiene una estructura de directorio como:
Después de agregar la carpeta de prueba, tendrá una estructura de directorios como:
Muchos paquetes de Python escritos correctamente usan la misma estructura. Un muy buen ejemplo es el paquete Boto. Consulta https://github.com/boto/boto
fuente
matplotlib
tiene enmatplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/… ), losklearn
tiene enscikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )Cómo lo hago...
Estructura de carpetas:
Setup.py apunta a src / como la ubicación que contiene los módulos de mis proyectos, luego ejecuto:
Lo que agrega mi proyecto en paquetes de sitio, apuntando a mi copia de trabajo. Para ejecutar mis pruebas uso:
Usando cualquier corredor de prueba que haya configurado.
fuente
code.py
. Tendría más sentido llamar al directorio de nivel superior "proyecto".Prefiero el directorio de pruebas de nivel superior. Esto significa que las importaciones se vuelven un poco más difíciles. Para eso tengo dos soluciones:
test_suite='tests.runalltests.suite'
asetup()
, y puede ejecutar las pruebas simplemente:python setup.py test
PYTHONPATH=. python tests/runalltests.py
Así es como el código en M2Crypto admite esas cosas:
Si prefiere realizar pruebas con pruebas nasales, es posible que deba hacer algo un poco diferente.
fuente
Usamos
En cada archivo de prueba insertamos
../src/
ensys.path
. No es la mejor solución, pero funciona. Creo que sería genial si alguien apareciera con algo como Maven en Java que le brinde convenciones estándar que simplemente funcionen, sin importar en qué proyecto trabaje.fuente
Si las pruebas son simples, simplemente colóquelas en la cadena de documentación; la mayoría de los marcos de prueba para Python podrán usar eso:
Para otras pruebas más complicadas, las pondría en
../tests/test_module.py
o dentrotests/test_module.py
.fuente
En C #, generalmente separé las pruebas en un ensamblaje separado.
En Python, hasta ahora, he tendido a escribir doctests, donde la prueba está en la cadena de documentación de una función, o ponerlos en el
if __name__ == "__main__"
bloque en la parte inferior del módulo.fuente
Al escribir un paquete llamado "foo", pondré pruebas unitarias en un paquete separado "foo_test". Los módulos y subpaquetes tendrán el mismo nombre que el módulo de paquete SUT. Por ejemplo, las pruebas para un módulo foo.xy se encuentran en foo_test.xy. Los archivos __init__.py de cada paquete de prueba contienen un conjunto AllTests que incluye todos los conjuntos de pruebas del paquete. setuptools proporciona una manera conveniente de especificar el paquete de prueba principal, de modo que después de "python setup.py desarrollo" puede usar "python setup.py test" o "python setup.py test -s foo_test.x.SomeTestSuite" Solo una suite específica.
fuente
Puse mis pruebas en el mismo directorio que el código bajo prueba (CUT); para
foo.py
las pruebas será enfoo_ut.py
o similar. (Modifico el proceso de descubrimiento de prueba para encontrarlos).Esto coloca las pruebas justo al lado del código en una lista de directorios, lo que hace obvio que las pruebas están allí, y hace que abrir las pruebas sea lo más fácil posible cuando están en un archivo separado. (Para editores de línea de comandos,
vim foo*
y cuando use un navegador de sistema de archivos gráfico, simplemente haga clic en el archivo CUT y luego en el archivo de prueba adyacente).Como otros han señalado , esto también hace que sea más fácil refactorizar y extraer el código para usarlo en otro lugar en caso de que sea necesario.
Realmente no me gusta la idea de poner pruebas en un árbol de directorios completamente diferente; ¿Por qué hacer que sea más difícil de lo necesario para los desarrolladores abrir las pruebas cuando abren el archivo con el CUT? No es que la gran mayoría de los desarrolladores estén tan interesados en escribir o ajustar pruebas que ignorarán cualquier barrera para hacerlo, en lugar de usar la barrera como excusa. (Todo lo contrario, en mi experiencia; incluso cuando lo haces lo más fácil posible, conozco a muchos desarrolladores que no pueden molestarse en escribir pruebas).
fuente
Recientemente comencé a programar en Python, por lo que aún no he tenido la oportunidad de encontrar las mejores prácticas. Pero, he escrito un módulo que va y encuentra todas las pruebas y las ejecuta.
Así que tengo:
Tendré que ver cómo va a medida que avance en proyectos más grandes.
fuente