¿Cuándo es apropiado no realizar pruebas unitarias?

139

Trabajo en una pequeña empresa como desarrollador en solitario. Soy el único desarrollador de la compañía, de hecho. Tengo varios proyectos (relativamente) grandes que he escrito y mantengo regularmente, y ninguno de ellos tiene pruebas para respaldarlos. Cuando comienzo nuevos proyectos, a menudo me pregunto si debería intentar un enfoque TDD. Parece una buena idea, pero honestamente nunca puedo justificar el trabajo extra involucrado.

Trabajo duro para ser progresista en mi diseño. Me doy cuenta de que ciertamente algún día otro desarrollador tendrá que mantener mi código, o al menos solucionarlo. Mantengo las cosas lo más simple posible y comento y documento cosas que serían difíciles de entender. Y el hecho es que estos proyectos no son tan grandes o complicados que un desarrollador decente tendría dificultades para comprenderlos.

Muchos de los ejemplos que he visto de pruebas se reducen a minucias y cubren todas las facetas del código. Como soy el único desarrollador y estoy muy cerca del código en todo el proyecto, es mucho más eficiente seguir un patrón de prueba de escritura y luego manual. También encuentro que los requisitos y las características cambian con la frecuencia suficiente para mantener las pruebas agregaría una cantidad considerable de resistencia en un proyecto. Tiempo que de otro modo podría gastarse en resolver las necesidades del negocio.

Así que termino con la misma conclusión cada vez. El retorno de la inversión es demasiado bajo.

De vez en cuando he configurado algunas pruebas para asegurarme de haber escrito un algoritmo correctamente, como calcular el número de años que alguien ha estado en la empresa en función de su fecha de contratación. Pero desde el punto de vista de la cobertura del código, he cubierto aproximadamente el 1% de mi código.

En mi situación, ¿aún encontraría una manera de hacer que las pruebas unitarias sean una práctica regular, o estoy justificado para evitar esa sobrecarga?

ACTUALIZACIÓN: Algunas cosas sobre mi situación que omití: Mis proyectos son todas aplicaciones web. Para cubrir todo mi código, tendría que usar pruebas de interfaz de usuario automatizadas, y esa es un área donde todavía no veo un gran beneficio sobre las pruebas manuales.

Ken Pespisa
fuente
1
Gracias a todos. Estoy aprendiendo mucho aquí. Dejé algunas cosas sobre mi situación: Mis proyectos son todas aplicaciones web. Para cubrir todo mi código, tendría que usar pruebas de interfaz de usuario automatizadas, y esa es un área donde todavía no veo un gran beneficio sobre las pruebas manuales.
Ken Pespisa
1
Estamos teniendo un gran éxito en Transactis utilizando la herramienta de prueba de automatización web de Telerik. Ya tenemos docenas de pruebas de navegador anteriormente manuales convertidas a automatización. Las pruebas automatizadas son MUCHO más rápidas y también son EXCELENTES para resaltar cualquier problema de rendimiento que pueda tener su sitio web.
John Kaster
2
He visto un proyecto que intentaba tener pruebas de navegador automatizadas de páginas web completas. Por lo que puedo decir, no ha encontrado ninguno de los cientos de errores graves que encontramos a través de las pruebas manuales, y costó una enorme cantidad de tiempo desarrollarlo y mantenerlo. (Usando Selenium impulsado por NUnit). Peor aún, algunas de las pruebas se rompen con frecuencia por problemas, debido a las incompatibilidades del navegador y el marco de prueba.
O'Rooney
1
Esto no es realmente una respuesta, solo una observación ... su argumento en contra de las pruebas unitarias porque "los requisitos cambian con demasiada frecuencia" me recuerda el argumento inverso que escucho donde trabajo: "nuestros programas son tan estáticos, ¿cuál es el punto de prueba? ¡Casi nunca cambia de todos modos! " ;)
Bane
2
Las pruebas de IU automatizadas de aplicaciones web no son pruebas unitarias, son una bestia completamente diferente y no te culparía si no quieres hacerlas. Pero todo su código de negocios debe estar en el backend, y eso es lo que debe probar.
Nyamiou The Galeanthrope

Respuestas:

85

Muchos de los ejemplos que he visto de pruebas se reducen a minucias y cubren todas las facetas del código.

¿Entonces? No tienes que probar todo . Solo las cosas relevantes.

Como soy el único desarrollador y estoy muy cerca del código en todo el proyecto, es mucho más eficiente seguir un patrón de prueba de escritura y luego manual.

Eso es realmente falso. No es más eficiente. Realmente es solo un hábito.

Lo que hacen otros desarrolladores en solitario es escribir un boceto o esquema, escribir los casos de prueba y luego completar el esquema con el código final.

Eso es muy, muy eficiente.

También encuentro que los requisitos y las características cambian con la frecuencia suficiente para mantener las pruebas agregaría una cantidad considerable de resistencia en un proyecto.

Eso también es falso. Las pruebas no son el arrastre. Los requisitos de cambios son el arrastre.

Tienes que arreglar las pruebas para reflejar los requisitos. Ya sea sus minucias, o de alto nivel; escrito primero o escrito al final.

El código no está listo hasta que pasen las pruebas. Esa es la única verdad universal del software.

Puede tener una prueba de aceptación limitada "aquí está".

O puede hacerse algunas pruebas unitarias.

O puedes tener ambos.

Pero no importa lo que haga, siempre hay una prueba para demostrar que el software funciona.

Sugeriría que un poco de formalidad y un buen conjunto de herramientas de prueba unitaria hacen que esa prueba sea mucho más útil.

S.Lott
fuente
8
Me gusta tu primera declaración, para probar solo las cosas relevantes. Con respecto a la eficiencia de la prueba manual versus la unidad, no creo que mi declaración sea completamente falsa, ni la suya es completamente cierta. Parece que hay un equilibrio entre las pruebas automáticas y manuales para lograr la máxima eficiencia.
Ken Pespisa
99
@Ken Pespisa: Lo siento. Tomé el TDD Kool-Aid hace unos dos años (después de 30 años de la última prueba). Ahora estoy atrapado en la prueba primero. Me hizo mucho, mucho más productivo porque tengo menos pensamientos para hacer cuando construyo.
S.Lott
3
@Ken Pespisa: No. Hay equilibrio en las respuestas. Si preguntara si es correcto dividir por cero, obtendría respuestas abrumadoras inclinadas en un sentido por una razón. Si preguntara si sqrt(-1)debería ser un número entero, obtendría respuestas abrumadoras que se inclinarían hacia un lado. El balance está en torno a "cómo" y "qué orden". El simple hecho es que debes probar. Así que primero escribe las pruebas y asegúrate de que funcionen.
S.Lott
21
Considere la posibilidad de probar la interfaz de la unidad, no los detalles de implementación. Prueba los límites y los casos fronterizos. Prueba el código arriesgado. Gran cantidad de código es lo suficientemente simple como para verificarlo mediante inspección, aunque inspeccionar su código es más propenso a errores que inspeccionar el código de otra persona. La primera vez que las pruebas manuales pueden ser más eficientes, por décima vez, las pruebas automatizadas están muy por delante.
BillThor
10
"El código no está listo hasta que pasen las pruebas" - En realidad no, en mi opinión. El código comienza cuando pasa las pruebas. El código no se realiza hasta que haya estado activo durante un año o dos y haya sido sometido a pruebas de estrés y pruebas de integración con una base de usuarios grande, activa e impaciente. Esa es la única prueba que realmente cuenta.
Vector
108

Imagine que tiene un conjunto de pruebas que pueden ejecutarse en un abrir y cerrar de ojos y encender una luz verde o roja. ¡Imagínese que este conjunto de pruebas lo probó todo ! Imagine que todo lo que tenía que hacer para ejecutar el conjunto de pruebas era escribir ^ T. ¿Qué poder te daría esto?

¿Podría hacer un cambio en el código sin temor a romper algo? ¿Podría agregar una nueva función sin temor a romper una antigua? ¿Podrías limpiar el código desordenado rápidamente sin temor a hacer daño?

¡Sí, podrías hacer todas esas cosas! ¿Y qué pasaría con su código con el tiempo? Se volvería más y más limpio porque no habría riesgo de limpiarlo.

Imaginemos que tienes una pequeña hada en tu hombro. Cada vez que escribes una línea de código, el hada agrega algo al conjunto de pruebas que prueba que esa línea de código hizo lo que se pretendía hacer. Entonces, cada dos segundos, podría presionar ^ T y ver que la última línea de código que escribió funcionó.

¿Cuánta depuración crees que harías?

Si esto suena como fantasía, tienes razón. Pero la realidad no es muy diferente. Reemplaza el parpadeo con unos segundos y el hada con la disciplina TDD, y ya lo tienes.

Digamos que está volviendo a un sistema que construyó hace un año, y ha olvidado cómo crear uno de los objetos centrales. Hay pruebas que crean ese objeto de todas las formas en que se puede crear. Puedes leer esas pruebas y refrescar tu memoria. ¿Necesita llamar a una API? Hay pruebas que llaman a esa API en todos los sentidos. Estas pruebas son pequeños documentos , escritos en un idioma que usted entiende. Son completamente inequívocos. Son tan formales que se ejecutan. ¡Y no pueden salir de la sincronización con la aplicación!

¿No vale la pena la inversión? ¡Tienes que estar bromeando! ¿Cómo podría alguien NO querer ese conjunto de pruebas? Hazte un favor y deja de discutir sobre tonterías. Aprenda a hacer TDD bien y observe cuánto más rápido va y cuánto más limpio es su código.

Tío Bob.
fuente
29
Wow, el tío Bob? Es genial tener tus pensamientos aquí. Estoy de acuerdo con usted en los beneficios de TDD, realmente no hay argumentos para tener allí. La pregunta es sobre la inversión de tiempo y el ROI. No es tonto para mí considerar estas cosas. Imagine que un proyecto me llevará un 50% más de tiempo para terminar con TDD que sin él, y el hada me dice que solo me ahorrará un 10% más de tiempo que las pruebas manuales durante la vida del proyecto. Puede parecer una fantasía, pero lo veo totalmente plausible con ciertos proyectos.
Ken Pespisa
11
@Ken "Imagine que un proyecto me llevará un 50% más de tiempo para terminar con TDD que sin él". Eso suena EXACTAMENTE como fantasía para mí. De hecho, parece que acabas de hacer esa figura en el acto sin una pizca de evidencia que lo respalde.
Rein Henrichs
18
@Rein Henrichs - Por supuesto que hice el número, fue una declaración hipotética. Estoy señalando que TDD agrega una cantidad significativa de tiempo a un proyecto, y tengo que considerar si voy a obtener algo de igual o mejor valor a cambio. No tienes que convencerme de los valores de TDD, estoy convencido. Pero no es una panacea.
Ken Pespisa
11
@Rein, ¿qué es exactamente la "evidencia disponible"? Por favor elabora.
Ken Pespisa
22
@ Tío Bob "Reemplaza el parpadeo con unos segundos": Estás bromeando, por supuesto. TDD es una buena herramienta, pero debe probar solo las partes relevantes; de lo contrario, pasará más tiempo manteniendo las pruebas que haciendo un desarrollo serio. Esto es especialmente cierto cuando los requisitos cambian muy rápidamente: constantemente estás escribiendo y tirando pruebas para clases que cambian todo el tiempo. No estoy diciendo que TDD sea malo, solo debe usarse con sensatez y no aplicarse mecánicamente como parece sugerir.
Giorgio
34

El error que está cometiendo es que está viendo las pruebas como una inversión de tiempo sin retorno inmediato. No necesariamente funciona así.

En primer lugar, escribir pruebas realmente te enfoca en lo que esta parte de tu código debe hacer.

En segundo lugar, ejecutarlos revela errores que de otro modo aparecerían en las pruebas.

En tercer lugar, ejecutarlos a veces muestra errores que de otro modo no aparecerían en las pruebas y luego realmente te morderían en la producción.

En cuarto lugar, si encuentra un error con un sistema que se está ejecutando y crea una prueba unitaria para él, no podrá volver a introducir ese error más tarde. Eso puede ser de gran ayuda. Los errores reintroducidos son comunes y muy molestos.

En quinto lugar, si alguna vez necesita entregar el código a otra persona, un conjunto de pruebas les facilitará la vida. Además, si ha ignorado un proyecto y vuelve a él después de unos años, ya no estará tan cerca de él y también será útil para usted.

Mi experiencia ha sido consistentemente que durante el desarrollo de un proyecto, tener pruebas unitarias decentes siempre ha hecho que el proceso sea más rápido y confiable.

glenatron
fuente
2
@Ken, las suites de prueba son especificaciones en forma ejecutable.
32

Los chicos de JUnit (marco de prueba de la Unidad Java) tienen la filosofía de que si es demasiado simple de probar, no lo pruebes . Recomiendo leer sus preguntas frecuentes sobre mejores prácticas , ya que es bastante pragmático.

TDD es un proceso diferente de escribir su software. La premisa básica detrás de las pruebas unitarias es que pasará menos tiempo en el depurador revisando el código, y descubrirá más rápidamente si su cambio de código rompe accidentalmente algo más en el sistema. Eso encaja con TDD. El ciclo TDD es así:

  1. Escribir una prueba
  2. Míralo fallar (prueba que tienes algo que hacer)
  3. Escriba exactamente lo que se necesita para pasar la prueba, no más.
  4. Míralo pasar (¡yay!)
  5. Refactor (hacerlo mejor)
  6. Lavar, enjuagar y repetir

Lo que es menos obvio sobre la aplicación de TDD es que cambia la forma en que escribe su código . Al obligarse a pensar en cómo probar / validar que el código está funcionando, está escribiendo código comprobable. Y dado que estamos hablando de pruebas unitarias, eso generalmente significa que su código se vuelve más modular. Para mí, el código modular y comprobable es una gran victoria por adelantado.

Ahora, ¿necesita probar cosas como las propiedades de C #? Imagine una propiedad definida como esta:

bool IsWorthTesting {get; set;}

La respuesta sería "no", no vale la pena probarlo, porque en este momento está probando la función de idioma. Solo confía en que los chicos de la plataforma C # lo hicieron bien. Además, si falla, ¿qué podrías hacer para arreglarlo?

Además, encontrará que hay ciertas partes de su código que muy bien requerirán demasiado esfuerzo para probarlas correctamente. Eso significa que no lo hagas, pero asegúrate de probar el código que usa / es usado por el problema complicado:

  • Se verificaron excepciones que solo pueden ocurrir si una instalación falla. Java tiene un montón de estos. Debe escribir un bloque catch o declarar la excepción marcada, incluso si no hay forma de que pueda fallar sin piratear los archivos instalados.
  • Interfaces de usuario. Encontrar el control bajo prueba e invocar los eventos correctos para simular las acciones de un usuario son muy problemáticos y, en algunos casos, imposibles. Sin embargo, si usa el patrón Modelo / Vista / Controlador, puede asegurarse de que su modelo y controladores se prueben y dejar la parte de la vista a prueba manual.
  • Interacciones cliente / servidor. Esto ya no es una prueba unitaria, y ahora es una prueba de integración . Escriba todas las partes que van hasta enviar y recibir mensajes por cable, pero en realidad no lo haga. Un buen enfoque es reducir la responsabilidad del código que realmente habla por cable a las comunicaciones en bruto. En el código de prueba de su unidad, simule el objeto de comunicación para asegurarse de que los servicios se comporten como espera.

Lo creas o no, TDD te ayudará a alcanzar un ritmo de desarrollo sostenible. No es por magia, sino porque tienes un ciclo de retroalimentación ajustado y eres capaz de atrapar errores realmente tontos rápidamente. El costo de corregir esos errores es esencialmente constante (al menos suficiente para fines de planificación) porque los pequeños errores nunca se convierten en grandes errores. Compare eso con la naturaleza explosiva de los sprints de borrachera / depuración de código.

Berin Loritsch
fuente
24

Debe equilibrar el costo de las pruebas con el costo de los errores.

Escribir una prueba de unidad de 10 líneas para una función que abre un archivo, donde la falla es "archivo no encontrado" no tiene sentido.

Una función que hace algo complejo a una estructura de datos compleja, entonces obviamente sí.

La parte difícil está en el medio. Pero recuerde que el valor real de las pruebas unitarias no es probar la función particular, sino probar las interacciones difíciles entre ellas. Entonces, una prueba de unidad que detecta que un cambio en un bit de código, rompe alguna función en un módulo diferente a 1000 líneas de distancia, vale su peso en café.

Martin Beckett
fuente
23

Las pruebas son juegos de azar.

Crear una prueba es una apuesta de que el costo de los errores en una unidad que ocurre y que no los atrapa con esa prueba (ahora y durante todas las revisiones futuras del código) es mayor que el costo de desarrollar la prueba. Esos costos de desarrollo de pruebas incluyen cosas como nómina para ingeniería de prueba adicional, tiempo de comercialización adicional, costos de oportunidad perdidos por no codificar otras cosas, etc.

Como cualquier apuesta, a veces ganas, a veces pierdes.

En algún momento, el software tardío con muchos menos errores gana sobre las cosas rápidas pero con errores que llegan primero al mercado. A veces lo contrario. Tienes que mirar las estadísticas en tu campo particular, y cuánto quiere apostar la administración.

Es posible que algunos tipos de errores no se realicen o que se eliminen de las pruebas de sanidad tempranas, de modo que estadísticamente no valga la pena el tiempo para crear pruebas específicas adicionales. Pero a veces el costo de un error es tan grande (médico, nuclear, etc.) que una empresa debe asumir una apuesta perdedora (similar a comprar un seguro). Muchas aplicaciones no tienen un costo de falla tan alto y, por lo tanto, no necesitan la mayor cobertura de seguro antieconómica. Otros lo hacen.

hotpaw2
fuente
3
Buena respuesta. Uno de los pocos que realmente responde a mi pregunta original. Me sumergí en el mundo de las pruebas desde que escribí esta publicación (me gusta por cierto). Necesito entenderla más antes de poder saber realmente cuándo usarla (o no). Por muchas de las razones indicadas aquí, preferiría usarlo todo el tiempo. Pero en última instancia dependerá de cuánto más rápido llegue, porque al final es una apuesta de mi tiempo, que está bajo el control de mi empresa / cliente, y a menudo se centran en las esquinas inferiores del triángulo del proyecto: en. wikipedia.org/wiki/Project_triangle
Ken Pespisa
10

Mi consejo es que solo pruebe el código que desea que funcione correctamente.

No pruebe el código que desea que tenga errores y que le cause problemas en el futuro.

Nick Hodges
fuente
99
Me recuerda el dicho que dice mi dentista: no tiene que usar hilo dental en todos sus dientes, solo los que desea conservar.
Ken Pespisa
Confieso que eso es lo que me hizo pensar en ello. ;-)
Nick Hodges
8

A menudo me pregunto si debería intentar un enfoque TDD. Parece una buena idea, pero honestamente nunca puedo justificar el trabajo extra involucrado.

TDD y Unit Testing no son lo mismo.

Puede escribir código y luego agregar pruebas unitarias más tarde. Eso no es TDD, y es mucho trabajo extra.

TDD es la práctica de codificación en un bucle de luz roja. Luz verde. Refactorizar iteraciones.

Esto significa escribir pruebas para el código que aún no existe, ver fallar las pruebas, arreglar el código para que las pruebas funcionen y luego hacer que el código sea "correcto". Esto a menudo te ahorra trabajo

Una de las ventajas de TDD es que reduce la necesidad de pensar en trivia. Cosas como los errores fuera de uno desaparecen. No tiene que buscar en la documentación de la API para averiguar si la lista que devuelve comienza en 0 o 1, simplemente hágalo.

Carnicero paul
fuente
¿Podría explicar cómo desaparecen los errores fuera de uno? ¿Está diciendo que puede obtener más rápidamente su respuesta sobre si el índice de una matriz está basado en cero o en uno a través de las pruebas que buscando en la documentación? Me parece poco probable: soy bastante rápido en Google :)
Ken Pespisa
1
En realidad, escribir TDD es una excelente manera de explorar una API (incluida una base de código heredada, con el propósito de documentar la funcionalidad).
Frank Shearar
También es muy útil si esa API cambia alguna vez ... De repente tienes algunas pruebas
fallidas
@Ken Pespisa, definitivamente es más rápido: escriba el código en función de si cree que es 0 o 1, ejecútelo y corríjalo si es necesario. La mayoría de las veces, tendrá razón y habría omitido tener que buscarlo, si está equivocado, lo sabe en 10 segundos.
Paul Butcher
Muy interesante beneficio. Como que me gusta eso.
Ken Pespisa
3

Trabajé en un sistema donde probamos casi todo. Las ejecuciones notables de las pruebas fueron el código de salida PDF y XLS.

¿Por qué? Pudimos probar las partes que recopilaron los datos y construimos el modelo que se utilizó para crear la salida. También pudimos probar las partes que descubrieron qué partes del modelo irían a los archivos PDF. No pudimos probar si el PDF se veía bien porque eso era totalmente subjetivo. No pudimos probar que todas las partes en un PDF fueran legibles para un usuario típico porque eso también era subjetivo. O si la elección entre barras y gráficos circulares era correcta para el conjunto de datos.

Si la salida va a ser subjetiva, hay pocas pruebas unitarias que puede hacer lo que vale la pena.

sal
fuente
En realidad, este tipo de prueba es probablemente "prueba de integración". Y sí, las pruebas de integración son mucho más difíciles que las pruebas unitarias, y una razón es que a veces las reglas para lo que es "correcto" son muy complicadas, o incluso subjetivas.
sleske
2

Para muchas cosas, una 'escritura-luego-prueba-manual' no toma más tiempo que escribir un par de pruebas. El ahorro de tiempo proviene de poder volver a ejecutar esas pruebas en cualquier momento.

Piense en ello: si tiene algún tipo de cobertura función decente con sus pruebas (que no debe confundirse con la cobertura de código), y supongamos que tiene 10 características - clic en un botón significa que tiene más o menos, 10 yous re-hacer sus pruebas ... mientras te sientas y tomas un café.

Tampoco tienes que probar las minutas. Puede escribir pruebas de integración que cubran sus características si no quiere llegar a los detalles esenciales ... En mi opinión, algunas pruebas unitarias son demasiado precisas para probar el idioma y la plataforma, y ​​no el código.

TL; DR Realmente nunca es apropiado porque los beneficios son demasiado buenos.

Steven Evers
fuente
2

Aquí hay dos respuestas muy buenas que he encontrado:

  1. Cuándo hacer una prueba unitaria versus una prueba manual
  2. ¿Qué no probar cuando se trata de pruebas unitarias?

Las justificaciones para evitar la sobrecarga percibida:

  • Ahorro de tiempo / costo inmediato para su empresa
  • Posible ahorro de tiempo / costos en la resolución de problemas / mantenibilidad / extensión a largo plazo incluso después de que usted se haya ido.

¿No le gustaría dejar un gran producto a su lado como prueba de la calidad de su trabajo? Hablando en términos egoístas, ¿no es mejor para ti que lo hagas?

Aditya P
fuente
1
Buena pregunta al final. Estoy orgulloso de mi trabajo, absolutamente, y mis aplicaciones funcionan muy bien (si puedo ser tan audaz). Pero tiene razón: podrían ser aún mejores con el apoyo de algunas pruebas. Creo que mi objetivo es tratar de incluir tantas pruebas útiles como sea posible dentro del tiempo que tengo que trabajar en el proyecto, y sin obsesionarme demasiado con la cobertura del código.
Ken Pespisa
1

Los desarrolladores profesionales escriben pruebas unitarias porque, a largo plazo, ahorran tiempo. Usted probará su código tarde o temprano, y si no lo hace, sus usuarios lo harán, y si tiene que corregir los errores más tarde, serán más difíciles de corregir y tendrán más efectos negativos.

Si está escribiendo código sin pruebas y no tiene errores, entonces está bien. Sin embargo, no creo que pueda escribir un sistema no trivial con cero errores, así que supongo que lo está probando de una forma u otra.

Las pruebas unitarias también son cruciales para evitar regresiones cuando modifica o refactoriza código antiguo. No prueban que su cambio no haya roto el código anterior, pero le brindan mucha confianza (siempre que pasen, por supuesto :))

No regresaría y escribiría un lote completo de pruebas para el código que ya ha enviado, pero la próxima vez que necesite modificar una función, le sugiero que intente escribir pruebas para ese módulo o clase, obtenga su cobertura hasta un 70% + antes de aplicar cualquier cambio. A ver si te ayuda.

Si lo prueba y puede decir honestamente que no fue de ayuda, entonces es lo suficientemente justo, pero creo que hay suficiente evidencia de la industria de que ayudan a que al menos valga la pena probar el enfoque.

Steve
fuente
Me gustan las ideas sobre cómo prevenir regresiones y agregar confianza. Esas son exactamente las razones por las que me gustaría agregar pruebas.
Ken Pespisa
1

Parece que la mayoría de las respuestas son pro-TDD, a pesar de que la pregunta no era sobre TDD sino sobre pruebas unitarias en general.

No hay una regla completamente objetiva detrás de qué prueba unitaria o no una prueba unitaria. Pero hay un par de veces en las que parece que muchos programadores no realizan pruebas unitarias:

  1. Métodos privados

Dependiendo de su filosofía OOP, puede crear métodos privados para desacoplar rutinas complejas de sus métodos públicos. Los métodos públicos generalmente están destinados a ser llamados en muchos lugares diferentes y se usan con frecuencia, y los métodos privados solo se llaman realmente por uno o dos métodos públicos en una clase o módulo para algo muy específico. Por lo general, es suficiente escribir pruebas unitarias para métodos públicos, pero no los métodos privados subyacentes que hacen que algo de la magia suceda. Si algo sale mal con un método privado, las pruebas de unidad de método público deberían ser lo suficientemente buenas como para detectar estos problemas.

  1. Las cosas que ya sabes deberían funcionar (o cosas probadas por otra persona)

Muchos programadores nuevos van en contra de esto cuando están aprendiendo a probar por primera vez, y piensan que necesitan probar cada línea que se está ejecutando. Si está utilizando una biblioteca externa y su funcionalidad está bien probada y documentada por sus autores, generalmente no tiene sentido probar la funcionalidad específica en las pruebas unitarias. Por ejemplo, alguien podría escribir una prueba para asegurarse de que su modelo ActiveRecord persista el valor correcto para un atributo con una devolución de llamada "before_save" a la base de datos, a pesar de que ese comportamiento ya está probado en Rails. Los métodos a los que llama la devolución de llamada, tal vez, pero no el comportamiento de devolución de llamada en sí. Cualquier problema subyacente con las bibliotecas importadas se revelaría mejor a través de pruebas de aceptación, en lugar de pruebas unitarias.

Ambos podrían aplicarse tanto si está haciendo TDD como si no.

Ravenstine
fuente
0

Ken, yo y muchos otros desarrolladores hemos llegado a la misma conclusión que tú varias veces a lo largo de nuestras carreras.

La verdad que creo que encontrará (como muchos otros) es que la inversión inicial de escribir pruebas para su aplicación puede parecer desalentadora, pero si se escribe bien y se dirige a las partes correctas de su código, realmente pueden ahorrar una tonelada de tiempo.

Mi gran problema fue con los marcos de prueba disponibles. Realmente nunca sentí que eran lo que estaba buscando, así que simplemente lancé mi propia solución muy simple. Realmente ayudó a llevarme al "lado oscuro" de las pruebas de regresión. Compartiré un pseudo fragmento básico de lo que hice aquí, y espero que pueda encontrar una solución que funcione para usted.

public interface ITest {
    public string Name {
        get;
    }
    public string Description {
        get;
    }
    public List<ITest> SubTests {
        get;
    }
    public TestResult Execute();
}

public class TestResult {
    public bool Succesful {
        get;
        set;
    }

    public string ResultMessage {
        get;
        set;
    }

    private Dictionary<ITest, TestResult> subTestResults = new Dictionary<ITest, TestResult>();
    public Dictionary<ITest, TestResult> SubTestResults {
        get {
            return subTestResults;
        }
        set {
            subTestResults = value;
        }
    }
}

La única parte difícil después de eso es descubrir qué nivel de granularidad crees que es la mejor opción para cualquier proyecto que estés haciendo.

Obviamente, crear una libreta de direcciones requerirá mucho menos pruebas que un motor de búsqueda empresarial, pero los fundamentos no cambian realmente.

¡Buena suerte!

Adam Carstensen
fuente
Creo que con el tiempo averiguaré qué nivel de granularidad es el mejor. Es bueno saber de otros que regularmente crean pruebas que lo abordan con sensatez y no escriben pruebas robóticamente para cada resultado concebible. Mi primera introducción a las pruebas fue en ese tipo de nivel donde todo debe ser probado. De hecho, todo el concepto de TDD parece seguir ese mantra.
Ken Pespisa
Creo que podría beneficiarse del uso de un Framework como SubSpec (está inspirado en BDD), por lo que le permitirá obtener el Aislamiento Assert ("SubTest") mientras comparte la configuración del contexto.
Johannes Rudolph el