unit-testing - unitario - unit testing ejemplos
Pautas de prueba de la unidad (7)
Con respecto a su última pregunta, en mi experiencia, la "buena" razón para no insistir en la cobertura del 100% de las pruebas es que se necesita una cantidad desproporcionada de esfuerzo para obtener los últimos puntos porcentuales, particularmente en las bases de códigos más grandes. Como tal, es una cuestión de decidir si vale la pena su tiempo una vez que llegue a ese punto de rendimientos decrecientes.
¿Alguien sabe dónde encontrar directrices y recomendaciones para las pruebas unitarias? Me gustaría tener algo que aborde los siguientes tipos de temas (por ejemplo):
- ¿Deben las pruebas estar en el mismo proyecto que la lógica de la aplicación?
- ¿Debería tener clases de prueba para reflejar mis clases de lógica o debería tener solo tantas clases de prueba como creo que necesito tener?
- ¿Cómo debo nombrar mis clases de prueba, métodos y proyectos (si van en diferentes proyectos)?
- ¿Deben probarse los métodos privados, protegidos e internos, o solo los que son de acceso público?
- ¿Deben separarse las pruebas de unidad y de integración?
- ¿Hay alguna buena razón para no tener una cobertura de prueba del 100%?
¿Qué no estoy preguntando sobre eso debería ser?
Un recurso en línea sería lo mejor.
En orden:
- No, generalmente es mejor incluirlos en un proyecto separado; a menos que desee poder ejecutar diagnósticos en tiempo de ejecución.
- Lo ideal es una cobertura de código del 100%, lo que significa que cada línea de código en cada rutina en cada clase.
- Voy con ClassnameTest, ClassnameTest.MethodNameTestnumber
- Todo.
- Yo diría que sí, ya que las pruebas de integración no necesitan ejecutarse si las pruebas de la unidad fallan.
- Las propiedades simples que acaban de establecer y obtener un campo no necesitan ser probadas.
Es una buena pregunta. Crecimos nuestro propio orgánicamente, y sospecho que la mejor manera es solo eso. Hay un poco "Depende ..." ahí.
Realizamos pruebas en el mismo proyecto, en un espacio de nombres secundario llamado "UnitTes"
Nuestras clases de prueba reflejan la clase lógica, para simplificar el seguimiento de dónde están las pruebas en relación con lo que están probando
Las clases se denominan como la clase lógica que están probando, los métodos se nombran para el escenario que están probando.
Solo escribimos pruebas para el público y los métodos internos (las pruebas se encuentran en el mismo proyecto) y aspiramos a una cobertura del 95% de la clase.
Prefiero no distinguir entre "unidad" e "intercesión". Se gastará mucho tiempo tratando de descubrir cuál es qué ... ¡ponle eso! Una prueba es una prueba.
100% es demasiado difícil de lograr todo el tiempo. Nuestro objetivo es el 95%. También hay rendimientos decrecientes sobre cuánto tiempo le tomará obtener el 5% final y lo que realmente captará.
Así somos nosotros y lo que se adaptaba al entorno y al ritmo. Tu kilometraje puede variar. Piensa en tu envolvimiento y las personalidades involucradas.
¡Espero ver lo que otros tienen que decir sobre este!
Insistentemente te recomiendo que leas Desarrollo basado en pruebas: por ejemplo y desarrollo basado en pruebas: una guía práctica Son demasiadas preguntas para un solo tema
La respuesta de Josh es correcta, solo un punto de aclaración:
La razón por la que se separan las pruebas unitarias de las pruebas de integración y aceptación es la velocidad. Yo uso TDD. Necesito comentarios inmediatos sobre la línea de código que acabo de crear / modificar. No puedo obtenerlo si estoy ejecutando un conjunto completo de pruebas de integración y / o aceptación, pruebas que afectan a discos reales, redes reales y sistemas externos realmente lentos e impredecibles.
No cruce las vigas. Cosas malas sucederán si lo haces.
¿Deben las pruebas estar en el mismo proyecto que la lógica de la aplicación?
Depende. Hay compensaciones de cualquier manera.
Mantenerlo en un proyecto requiere un ancho de banda adicional para distribuir su proyecto, tiempo de construcción adicional e incrementa el espacio de instalación, y hace que sea más fácil cometer el error de tener una lógica de producción que dependa del código de prueba.
Por otro lado, mantener proyectos separados puede hacer que sea más difícil escribir pruebas que involucren métodos / clases privadas (dependiendo del lenguaje de programación) y cause problemas menores de administración, como crear un nuevo entorno de desarrollo (por ejemplo, cuando un nuevo desarrollador se une al proyecto) más difícil.
Cuánto cuestan estos diferentes costos varía según el proyecto, por lo que no hay una respuesta universal.
¿Debería tener clases de prueba para reflejar mis clases de lógica o debería tener solo tantas clases de prueba como creo que necesito tener?
No.
Debe tener clases de prueba que permitan un código de prueba bien factorizado (es decir, duplicación mínima, intento claro, etc.).
La ventaja obvia de reflejar directamente las clases lógicas en las clases de prueba es que facilita la búsqueda de las pruebas correspondientes a un fragmento de código en particular. Hay otras maneras de resolver este problema sin restringir la flexibilidad del código de prueba. Convenciones de nomenclatura simples para módulos de prueba y clases son usualmente suficientes.
¿Cómo debo nombrar mis clases de prueba, métodos y proyectos (si van en diferentes proyectos)?
Debes nombrarlos para que:
- cada clase de prueba y método de prueba tiene un propósito claro, y
- para que alguien que busca una prueba en particular (o para pruebas sobre una unidad en particular) pueda encontrarla fácilmente.
¿Deben probarse los métodos privados, protegidos e internos, o solo los que son de acceso público?
A menudo, los métodos no públicos deben probarse. Depende de si obtiene la confianza suficiente de solo probar la interfaz pública, o si la unidad que realmente desea probar no es públicamente accesible.
¿Deben separarse las pruebas de unidad y de integración?
Esto depende de su elección de marco (s) de prueba. Haga lo que mejor funcione con su (s) marco (s) de prueba y haga que:
- tanto la unidad como las pruebas de integración relacionadas con un fragmento de código son fáciles de encontrar,
- es fácil ejecutar solo las pruebas unitarias,
- es fácil ejecutar solo las pruebas de integración,
- es fácil ejecutar todas las pruebas.
¿Hay alguna buena razón para no tener una cobertura de prueba del 100%?
Sí, hay una buena razón. Estrictamente hablando, "cobertura 100% de prueba" significa que cada situación posible en su código se ejerce y prueba. Esto es simplemente poco práctico para casi cualquier proyecto.
Si simplemente toma "100% de cobertura de prueba" para indicar que cada línea de código fuente es ejercida por el conjunto de pruebas en algún momento, entonces este es un buen objetivo, pero a veces hay solo un par de líneas en lugares difíciles que son difíciles para alcanzar con pruebas automatizadas. Si el costo de verificar manualmente esa funcionalidad es menor que el costo de pasar por contorsiones para llegar a esas últimas cinco líneas, entonces esa es una buena razón para no tener una cobertura de línea del 100%.
En lugar de una regla simple de que debe tener una cobertura de línea del 100%, anime a los desarrolladores a descubrir las lagunas en sus pruebas y encuentre la manera de solucionarlas, ya sea que mejore el número de líneas "cubiertas". En otras palabras, si mide las líneas cubiertas, mejorará la cobertura de su línea, pero lo que realmente desea es una mejor calidad. Así que no olvides que la cobertura de línea es solo una aproximación muy cruda de calidad.
Recomendaría el libro de Kent Beck sobre TDD.
Además, debe ir al sitio de Martin Fowler . También tiene mucha información buena sobre las pruebas.
Somos bastante grandes en TDD, así que responderé a las preguntas desde esa perspectiva.
¿Deben las pruebas estar en el mismo proyecto que la lógica de la aplicación?
Por lo general, mantenemos nuestras pruebas en la misma solución, pero dividimos las pruebas en DLL / Proyectos separados que reflejan los DLL / Proyectos que están probando, pero mantienen los espacios de nombres con las pruebas en un espacio de nombres secundario. Ejemplo: Common / Common.Tests
¿Debería tener clases de prueba para reflejar mis clases de lógica o debería tener solo tantas clases de prueba como creo que necesito tener?
Sí, sus pruebas deben crearse antes de que se creen clases y, por definición, solo debe probar una sola unidad aisladamente. Por lo tanto, debe tener una clase de prueba para cada clase en su solución.
¿Cómo debo nombrar mis clases de prueba, métodos y proyectos (si van en diferentes proyectos)?
Me gustaría enfatizar que el comportamiento es lo que se está probando, por lo que normalmente llamo clases de prueba después del SUT. Por ejemplo, si tuviera una clase de usuario, nombraría la clase de prueba así:
public class UserBehavior
Los métodos deben nombrarse para describir el comportamiento que espera.
public void ShouldBeAbleToSetUserFirstName()
Los proyectos pueden nombrarse de la manera que desee, pero generalmente quiere que sea bastante obvio qué proyecto está probando. Ver la respuesta anterior sobre la organización del proyecto.
¿Deben probarse los métodos privados, protegidos e internos, o solo los que son de acceso público?
De nuevo, desea pruebas para afirmar el comportamiento esperado como si fuera un consumidor externo de los objetos que se están probando. Si prueba detalles de implementación interna, sus pruebas serán frágiles. Desea que su prueba le brinde la libertad de refactorizar sin preocuparse por romper la funcionalidad existente. Si su prueba conoce los detalles de implementación, tendrá que cambiar sus pruebas si esos detalles cambian.
¿Deben separarse las pruebas de unidad y de integración?
Sí, las pruebas unitarias deben aislarse de las pruebas de aceptación e integración. La separación de preocupaciones también se aplica a las pruebas.
¿Hay alguna buena razón para no tener una cobertura de prueba del 100%?
No me gustaría colgar en la cuestión de la cobertura del código 100%. La cobertura del 100% del código tiende a implicar cierto nivel de calidad en las pruebas, pero eso es un mito. Puede tener pruebas terribles y obtener una cobertura del 100%. En cambio, confiaría en una buena mentalidad de Prueba Primero. Si siempre escribe una prueba antes de escribir una línea de código, garantizará una cobertura del 100%, por lo que se convertirá en un punto discutible.
En general, si te enfocas en describir el alcance total del comportamiento de la clase, entonces no tendrás nada de qué preocuparte. Si haces que la cobertura del código sea una métrica, los programadores perezosos simplemente harán lo suficiente para cumplir con esa marca y todavía tendrás pruebas de mierda. En su lugar, confíe mucho en las evaluaciones por pares donde también se revisan las pruebas.