En mi opinión, las pruebas unitarias deben colocarse en un ensamblaje separado del código de producción. Aquí hay algunas desventajas de colocar pruebas unitarias en el mismo ensamblaje o ensambles que el código de producción:
- Las pruebas unitarias se envían con el código de producción. Lo único que se envía con el código del producto es el código de producción.
- Los ensamblajes se hincharán innecesariamente por pruebas unitarias.
- Las pruebas unitarias pueden afectar los procesos de compilación como la compilación automática o continua.
Realmente no conozco a ningún profesional. Tener un proyecto adicional (o 10) no es una estafa.
Editar: más información sobre compilación y envío
Además, recomendaría que cualquier proceso de construcción automatizado coloque la producción y las pruebas unitarias en diferentes ubicaciones. Idealmente, el proceso de compilación de prueba unitaria solo se ejecuta si se compila el código de producción y copia los archivos del producto en el directorio de pruebas unitarias. Hacerlo de esta manera da como resultado que los bits reales se separen para el envío, etc. Además, es bastante trivial ejecutar pruebas unitarias automatizadas en este punto en todas las pruebas en un directorio particular.
Para resumir, aquí está la idea general de una compilación diaria y prueba y envío de bits y otros archivos:
- La compilación de producción se ejecuta y coloca los archivos de producción en un directorio específico de "producción".
- Construir proyectos de producción solamente.
- Copie bits compilados y otros archivos en un directorio de "producción".
- Copie bits y otros archivos en un directorio de candidatos de lanzamiento, también conocido como un directorio de lanzamiento de Navidad sería "Release20081225".
- Si la compilación de producción tiene éxito, se ejecuta la compilación de prueba unitaria.
- Copie el código de producción al directorio "pruebas".
- Construya pruebas unitarias en el directorio "pruebas".
- Ejecute pruebas unitarias.
- Enviar notificaciones de compilación y resultados de pruebas unitarias a los desarrolladores.
- Cuando se acepta un candidato de lanzamiento (como Release20081225), envíe estos bits.
#if
. Este símbolo personalizado se puede alternar utilizando los parámetros de la línea de comandos del compilador en sus scripts de software de CI. Ver msdn.microsoft.com/en-us/library/4y6tbswk.aspx .Proyecto separado, pero en la misma solución. (He trabajado en productos con soluciones separadas para el código de prueba y producción, es horrible. Siempre estás cambiando entre los dos)
Los motivos de los proyectos separados son los establecidos por otros. Tenga en cuenta que si está utilizando pruebas basadas en datos, podría terminar con una cantidad bastante considerable de hinchazón si incluye las pruebas en el ensamblaje de producción.
Si necesita acceso a los miembros internos del código de producción, use InternalsVisibleTo .
fuente
[assembly:InternalsVisibleTo("UnitTestProjectName")]
a suAssemblyInfo.cs
archivo de proyecto .No entiendo la frecuente objeción a implementar pruebas con código de producción. Dirigí un equipo en un pequeño microcap (creció de 14 a 130 personas). Teníamos media docena de aplicaciones Java y nos pareció extremadamente valioso implementar pruebas en el campo para ejecutarlas en un determinadomáquina que exhibía un comportamiento inusual. Se producen problemas aleatorios en el campo y ser capaz de lanzar unos pocos miles de pruebas unitarias al misterio con un costo cero fue invaluable y a menudo se diagnosticaron problemas en minutos ... incluyendo problemas de instalación, problemas de RAM escamosos, problemas específicos de la máquina, problemas de red escamosos, etc, etc. Creo que es increíblemente valioso poner pruebas en el campo. Además, surgen problemas aleatorios en momentos aleatorios y es bueno tener las pruebas unitarias allí esperando a ser ejecutadas en cualquier momento. El espacio en el disco duro es barato. Al igual que tratamos de mantener juntos los datos y las funciones (diseño OO), creo que hay algo fundamentalmente valioso en mantener juntos el código y las pruebas (función + pruebas que validan las funciones).
Me gustaría poner mis pruebas en el mismo proyecto en C # / .NET / Visual Studio 2008, pero todavía no he investigado esto lo suficiente como para lograrlo.
¡Una gran ventaja de mantener a Foo.cs en el mismo proyecto que FooTest.cs es que a los desarrolladores se les recuerda constantemente cuando una clase se pierde una prueba de hermanos! Esto fomenta mejores prácticas de codificación basadas en pruebas ... los agujeros son más evidentes.
fuente
Ponga las pruebas unitarias en el mismo proyecto que el código para lograr una mejor encapsulación.
Puede probar fácilmente los métodos internos, lo que significa que no hará públicos los métodos que deberían haber sido internos.
También es realmente bueno tener las pruebas unitarias cerca del código que está escribiendo. Cuando escribe un método, puede encontrar fácilmente las pruebas unitarias correspondientes porque está en el mismo proyecto. Cuando construye un ensamblaje que incluye unitTests, cualquier error en unitTest le dará un error de compilación, por lo que debe mantener su unittest actualizado, solo para compilar. Tener unittest en un proyecto separado puede hacer que algunos desarrolladores olviden construir el unittest-project y se pierdan las pruebas rotas por un tiempo.
Y puede eliminar las pruebas unitarias del código de producción, utilizando etiquetas de compilación (IF #Debug).
Las pruebas de integración automática (hechas en i NUnit) deben estar en un proyecto separado ya que no pertenecen a ningún proyecto en particular.
fuente
Release
compilación y pocos "heisenbugs" pueden caer.InternalsVisibleTo
permite probar métodos internos de un proyecto de prueba separadoDebug
,Approval
yRelease
; y compilar aprobación con todas las optimizaciones de lanzamiento. Además, en general, las pruebas unitarias no son excelentes para detectar heisenbugs en primer lugar (en mi experiencia). Tiende a necesitar pruebas de regresión de integración específicas para esos, y puede colocarlos uno al lado del otro.Después de pasar un tiempo en proyectos TypeScript, donde las pruebas a menudo se colocan en un archivo junto con el código que están probando, crecí prefiriendo este enfoque en lugar de mantenerlos separados:
Entonces, cuando comencé un nuevo proyecto .NET Core recientemente, quería ver si era posible imitar esta estructura en un proyecto de C # sin enviar las pruebas o los ensambles de prueba con la versión final.
Poner las siguientes líneas en el archivo del proyecto parece estar funcionando bien hasta ahora:
Lo anterior asegura que en la
Release
configuración todos los archivos nombrados*.Tests.cs
se excluyan de la compilación, y también que se eliminen las referencias del paquete de pruebas de unidad requeridas.Si aún desea poder probar las clases en su configuración de lanzamiento, puede crear una nueva configuración derivada de
Release
algo así llamadoReleaseContainingTests
.Actualización: después de usar esta técnica durante un tiempo, también he descubierto que es útil personalizar sus iconos en VS Code para que las pruebas (y otras cosas) se destaquen un poco más en el panel del explorador:
Para hacer esto, use la extensión Tema de icono de material y agregue algo como lo siguiente a sus preferencias de código VS JSON:
fuente
Mis pruebas unitarias siempre van en un proyecto separado. De hecho, para cada proyecto que tengo en mi solución, hay un proyecto de prueba separado que lo acompaña. El código de prueba no es un código de aplicación y no debe mezclarse con él. Una ventaja de mantenerlos en proyectos separados, al menos usando TestDriven.Net, es que puedo hacer clic derecho en un proyecto de prueba y ejecutar todas las pruebas en ese proyecto, probando una biblioteca completa de código de aplicación con un solo clic.
fuente
Si se usa el marco NUnit , hay una razón adicional para poner las pruebas en el mismo proyecto. Considere el siguiente ejemplo del código de producción mezclado con pruebas unitarias:
Las pruebas unitarias aquí sirven como documentación y especificación del código que se está probando. No sé cómo lograr este efecto de autodocumentación, con las pruebas ubicadas en un proyecto separado. El usuario de la función tendría que buscar las pruebas para ver esos casos de prueba, lo cual es poco probable.
Actualización : Sé que tal uso del
TestCase
atributo no fue lo que los desarrolladores de NUnit pretendieron, pero ¿por qué no?fuente
Fluctúo entre el mismo proyecto y diferentes proyectos.
Si está lanzando una biblioteca, lanzar el código de prueba con el código de producción es un problema, de lo contrario, creo que generalmente no lo es (aunque hay una fuerte barrera psicológica antes de intentarlo).
Al poner las pruebas en el mismo proyecto, me resulta más fácil cambiar entre las pruebas y el código que prueban, y más fácil refactorizarlas / moverlas.
fuente
Los puse en proyectos separados. El nombre del ensamblado refleja el de los espacios de nombres, como regla general para nosotros. Entonces, si hay un proyecto llamado Company.Product.Feature.sln, tiene una salida (nombre de ensamblado) de Company.Product.Feature.dll. El proyecto de prueba es Company.Product.Feature.Tests.sln, produciendo Company.Product.Feature.Tests.dll.
Es mejor mantenerlos en una única solución y controlar la salida a través del Administrador de configuración. Tenemos una configuración con nombre para cada una de las ramas principales (Desarrollo, Integración, Producción) en lugar de usar la depuración y versión predeterminadas. Una vez que haya configurado sus configuraciones, puede incluirlas o excluirlas haciendo clic en la casilla de verificación "Compilar" en el Administrador de configuración. (Para obtener el Administrador de configuración, haga clic con el botón derecho en la solución y vaya al Administrador de configuración). Tenga en cuenta que a veces el CM en Visual Studio tiene errores. Un par de veces, tuve que ir al proyecto y / o archivos de solución para limpiar los objetivos que creó.
Además, si está utilizando Team Build (y estoy seguro de que otras herramientas de compilación .NET son las mismas), puede asociar la compilación con una configuración con nombre. Esto significa que si no construye sus pruebas unitarias para su construcción "Producción", por ejemplo, el proyecto de construcción también puede conocer esta configuración y no construirlas ya que se marcaron como tales.
Además, solíamos hacer XCopy de la máquina de compilación. El script simplemente omitiría la copia de cualquier cosa llamada * .Tests.Dll de ser implementada. Fue simple, pero funcionó.
fuente
Yo diría que los mantenga separados.
Además de las otras razones mencionadas, tener código y pruebas juntas sesga los números de cobertura de prueba. Cuando informa sobre cobertura de prueba unitaria: la cobertura informada es mayor porque las pruebas están cubiertas cuando ejecuta pruebas unitarias. Cuando informa sobre la cobertura de la prueba de integración, la cobertura informada es menor porque las pruebas de integración no ejecutarían pruebas unitarias.
fuente
Estoy realmente inspirado por el marco de prueba de unidad de la biblioteca Flood NN de Robert Lopez. Utiliza un proyecto diferente para cada clase de unidad probada, y tiene una solución que contiene todos estos proyectos, así como un proyecto principal que compila y ejecuta todas las pruebas.
Lo bueno es también el diseño del proyecto. Los archivos de origen están en una carpeta, pero la carpeta para el proyecto VS está debajo. Esto le permite crear diferentes subcarpetas para diferentes compiladores. Todos los proyectos VS se envían con el código, por lo que es muy fácil para cualquiera ejecutar cualquiera o todas las pruebas unitarias.
fuente
Sé que esta es una pregunta muy antigua, pero me gustaría agregar mi experiencia allí. Recientemente cambié el hábito de las pruebas unitarias de proyectos separados al mismo.
¿Por qué?
Primero, tiendo a mantener la estructura de la carpeta principal del proyecto igual con el proyecto de prueba. Entonces, si tengo un archivo debajo,
Providers > DataProvider > SqlDataProvider.cs
entonces estoy creando la misma estructura en mis proyectos de prueba unitaria comoProviders > DataProvider > SqlDataProvider.Tests.cs
Pero después de que el proyecto se hace cada vez más grande, una vez que mueve los archivos de una carpeta a otra, o de un proyecto a otro, se está volviendo un trabajo muy engorroso sincronizarlos con los proyectos de prueba unitaria.
En segundo lugar, no siempre es muy fácil navegar desde la clase que se va a probar hasta la clase de prueba unitaria. Esto es aún más difícil para JavaScript y Python.
Recientemente, comencé a practicar que, cada archivo que creé (por ejemplo
SqlDataProvider.cs
) estoy creando otro archivo con sufijo de prueba, comoSqlDataProvider.Tests.cs
Al principio parece que hinchará archivos y referencias de bibliotecas, pero a largo plazo, eliminará el síndrome del archivo móvil a primera vista, y también se asegurará de que cada archivo que sean candidatos para ser probados tenga un archivo par con
.Tests
sufijo Le permite saltar fácilmente al archivo de prueba (porque está uno al lado del otro) en lugar de mirar a través de un proyecto separado.Incluso puede escribir reglas comerciales para escanear a través del proyecto e identificar la clase que no tiene el archivo .Tests e informarlas al propietario. También puede decirle a su corredor de prueba fácilmente que apunte a las
.Tests
clases.Especialmente para Js y Python, no necesitará importar sus referencias desde una ruta diferente, simplemente puede usar la misma ruta del archivo de destino que se está probando.
Estoy usando esta práctica durante un tiempo, y creo que es una compensación muy razonable entre el tamaño del proyecto y la capacidad de mantenimiento y la curva de aprendizaje para los recién llegados al proyecto.
fuente
Como otros han respondido: ponga pruebas en proyectos separados
Una cosa que no se ha mencionado es el hecho de que en realidad no se puede ejecutar
nunit3-console.exe
contra nada más que.dll
archivos.Si planea ejecutar sus pruebas a través de TeamCity, esto planteará un problema.
Digamos que tiene un proyecto de aplicación de consola. Cuando compila, devuelve un ejecutable
.exe
a labin
carpeta.Desde allí
nunit3-console.exe
no podrá ejecutar ninguna prueba definida en esa aplicación de consola.En otras palabras, una aplicación de consola devuelve un
exe
archivo y una biblioteca de clase devuelvedll
archivos.Hoy acabo de morder esto y apesta :(
fuente
Recientemente he estado implementando en Docker. No veo el valor de tener un proyecto separado cuando Dockerfile puede copiar fácilmente el directorio / src y abandonar el directorio / test. Pero soy nuevo en dotnet y podría faltar algo.
fuente
Proyectos separados, aunque debate conmigo mismo si deberían compartir el mismo svn. Por el momento, les estoy dando repositorios svn separados, uno llamado
"MyProject" - para el proyecto en sí
y uno llamado
"MyProjectTests": para las pruebas asociadas con MyProject.
Esto es bastante limpio y tiene la ventaja de que el compromiso con el proyecto y el compromiso con las pruebas están bastante separados. También significa que puede entregar el svn del proyecto si es necesario, sin tener que liberar sus pruebas. También significa que puede tener directorios de sucursales / troncales / etiquetas para sus pruebas y para su proyecto.
Pero estoy cada vez más inclinado a tener algo como lo siguiente, en un único repositorio svn, para cada proyecto.
Me interesaría saber qué piensan otras personas sobre esta solución.
fuente