unit testing - que - Comienzo de TDD-¿Desafíos? Soluciones? Recomendaciones?
pruebas funcionales bdd (11)
De acuerdo, sé que ya ha habido preguntas sobre cómo empezar con TDD . Sin embargo, creo que sé que el consenso general es simplemente hacerlo . Sin embargo, parece que tengo los siguientes problemas para entrar en el juego:
- Cuando trabaje con colecciones, ¿todavía se probará si el add / remove / insert obvio es exitoso, incluso cuando se basa en Generics, etc. donde "sabemos" que va a funcionar?
- Algunas pruebas parecen demorar una eternidad en implementarse. Por ejemplo, cuando se trabaja con un string output, ¿hay una "mejor" forma de abordar este tipo de cosas? (por ejemplo, prueba el modelo de objetos antes de analizar, divide el análisis en pequeñas operaciones y prueba allí). En mi opinión, siempre debes probar el "resultado final", pero eso puede variar enormemente y ser tedioso de configurar.
- No tengo un marco de prueba para usar (el trabajo no pagará por uno) para poder "practicar" más. ¿Hay algunos buenos que sean gratuitos para uso comercial? (en este momento estoy usando good ''ol Debug.Assert :)
- Probablemente el más grande .. A veces no sé qué esperar que NO suceda ... Es decir, recibes luz verde, pero siempre me preocupa que pueda faltarme una prueba ... ¿Excavas más para intentar romper el código, o déjalo estar y espera a que todo caiga más tarde (lo que costará más) ...
Básicamente, lo que busco aquí no es un " solo hazlo " sino más " Hice esto, tuve problemas con esto, los resolví con esto ". La experiencia personal :)
Creo que lo más importante (y en realidad uno de los grandes resultados de, de una manera un tanto recursiva) TDD es la gestión exitosa de las dependencias. Debe asegurarse de que los módulos se prueban de forma aislada sin necesidad de una configuración complicada. Por ejemplo, si está probando un componente que finalmente envía un correo electrónico, haga que el remitente sea una dependencia para que pueda simularlo en sus pruebas. Esto lleva a un segundo punto: los burlones son tus amigos. Familiarícese con los marcos burlones y el estilo de las pruebas que promueven (conductuales, a diferencia del clásico basado en el estado) y las elecciones de diseño que fomentan (el principio "Diga, no pregunte" ).
De mi propia experiencia:
Solo pruebe su propio código, no el código del marco subyacente. Entonces, si está utilizando una lista genérica, entonces no es necesario probar Agregar, Eliminar, etc.
No hay 2. ¡Mire allí! ¡Monos!
NUnit es el camino a seguir.
Definitivamente no puedes probar cada resultado. Pruebo lo que espero que pase, y luego pruebo algunos casos extremos en los que espero obtener excepciones o respuestas no válidas. Si aparece un error en la pista debido a algo que olvidaste probar, lo primero que debes hacer (antes de tratar de corregir el error) es escribir una prueba para probar que el error existe.
Descubrí que los principios ilustrados en las tres tarjetas de índice para recordar fácilmente la esencia de TDD son una buena guía.
De todos modos, para responder a sus preguntas
- No tienes que probar algo que "sabes" va a funcionar, a menos que lo hayas escrito. No escribiste genéricos, Microsoft lo hizo;)
- Si necesita hacer tanto para su prueba, tal vez su objeto / método también esté haciendo demasiado.
- Descargue TestDriven.NET para comenzar de inmediato las pruebas unitarias en su Visual Studio (excepto si se trata de una edición Express)
- Simplemente prueba lo correcto que sucederá . No es necesario que pruebe todo lo que puede salir mal: tiene que esperar que las pruebas fallen.
En serio, solo hazlo, amigo. :)
El consejo anterior es bueno, y si desea una lista de marcos libres, no debe buscar más allá de la Lista de marcos xUnit en Wikipedia. Espero que esto ayude :)
En mi opinión (su millaje puede variar):
1- Si no lo escribiste, no lo pruebes. Si lo escribió y no tiene una prueba, no existe.
3- Como todo el mundo ha dicho, xUnit es gratis y excelente.
2 y 4 Decidir exactamente qué probar es una de esas cosas sobre las que puedes debatir contigo mismo para siempre. Intento dibujar esta línea usando los principios del diseño por contrato. Consulte la ''Construcción de software orientada a objetos'' o ''El programador pragmático'' para más detalles al respecto.
Mantenga las pruebas cortas, "atómicas". Pruebe la suposición más pequeña en cada prueba. Haga que cada TestMethod sea independiente; para las pruebas de integración, incluso creo una nueva base de datos para cada método. Si necesita construir algunos datos para cada prueba, use un método "Init". Usa simulacros para aislar la clase de tus pruebas de sus dependencias.
Siempre pienso "¿cuál es la cantidad mínima de código que necesito escribir para probar que esto funciona en todos los casos?"
Mi opinión sobre esto es la siguiente:
- +1 por no probar el código de la infraestructura, pero es posible que aún deba probar las clases derivadas de las clases de framework.
- Si alguna clase / método es difícil de probar, puede ser una fuerte indicación de que algo anda mal con el diseño. Intento seguir el principio "1 clase - 1 responsabilidad, 1 método - 1 acción". De esta forma, podrá probar métodos complejos mucho más fácilmente al hacerlo en porciones más pequeñas.
- +1 para xUnit. Para Java, también puedes considerar TestNG .
- TDD no es un evento único, es un proceso. Así que no trates de imaginar todo desde el principio, pero asegúrate de que cada error encontrado en el código esté cubierto por la prueba una vez que se descubra.
No soy un experto en TDD, de ninguna manera, pero esta es mi opinión:
- Si es completamente trivial (getters / setters, etc.) no lo pruebe, a menos que no tenga confianza en el código por alguna razón.
- Si es un método bastante simple pero no trivial, pruébelo. La prueba es probablemente fácil de escribir de todos modos.
- Cuando se trata de qué esperar que no ocurra, diría que si un determinado problema potencial es responsabilidad de la clase que está evaluando, debe probar que lo maneja correctamente. Si no es la responsabilidad de la clase actual, no la pruebe.
Los marcos de prueba de xUnit son a menudo de uso gratuito, así que si eres un chico de .Net, echa un vistazo a NUnit, y si Java es lo tuyo, echa un vistazo a JUnit.
En el último año me he convencido cada vez más de los beneficios de TDD. Las cosas que aprendí en el camino: 1) la inyección de dependencia es tu amiga. No estoy hablando de inversión de contenedores de control y frameworks para ensamblar arquitecturas de plugins, simplemente pasando dependencias al constructor del objeto bajo prueba. Esto devuelve enormes dividendos en la capacidad de prueba de su código. 2) Partí con la pasión / fanatismo del converso y tomé un marco burlón y comencé a usar burlas para todo lo que pude. Esto condujo a pruebas frágiles que requirieron mucha configuración dolorosa y que se caerían tan pronto como comenzara cualquier refactorización. Use el tipo correcto de prueba doble. Falsificaciones donde solo necesita respetar una interfaz, stubs para enviar datos al objeto bajo prueba, simular solo donde le importa la interacción. 3) La prueba debe ser pequeña. Apunte a una afirmación o interacción que se prueba en cada prueba. Intento hacer esto y sobre todo estoy allí. Se trata de la solidez del código de prueba y también acerca de la cantidad de complejidad en una prueba cuando necesita volver a visitarla más tarde.
El mayor problema que he tenido con TDD ha sido trabajar con una especificación de un organismo de estándares y una implementación de terceros de ese estándar que era el estándar de facto. Codifiqué un montón de pruebas de unidad muy buenas a la letra de la especificación solo para descubrir que la implementación del otro lado de la valla vio el estándar como más un documento de asesoramiento. Ellos jugaron bastante flojos con eso. La única forma de solucionar esto era probar con la implementación y las pruebas unitarias y refactorizar las pruebas y el código según sea necesario. El verdadero problema fue la creencia de mi parte de que, siempre que tuviera pruebas de código y unidad, todo estaba bien. No tan. Necesita construir salidas reales y realizar pruebas funcionales al mismo tiempo que está probando la unidad. Pequeñas piezas de beneficio durante todo el proceso, en manos de usuarios o partes interesadas.
Solo como una adición a esto, pensé que diría que publiqué una publicación de blog sobre mis pensamientos para comenzar con las pruebas (siguiendo esta discusión y mi propia investigación), ya que puede ser útil para las personas que ven este hilo.
" TDD - Comenzando con el desarrollo basado en pruebas " - Hasta ahora he recibido excelentes comentarios y realmente apreciaría mucho más que ustedes puedan ofrecer.
¡Espero que esto ayude! :)
Primero, está bien y es normal sentirse frustrado cuando comienzas a tratar de usar TDD en tu estilo de codificación. Simplemente no te desanimes y renuncies, necesitarás darle algo de tiempo. Es un gran cambio de paradigma en la manera en que pensamos resolver un problema en el código. Me gusta pensar en eso cuando cambiamos de programación procedural a orientada a objetos.
En segundo lugar, creo que el desarrollo basado en pruebas es ante todo una actividad de diseño que se utiliza para desarrollar el diseño de un componente mediante la creación de una prueba que describa primero la API que va a exponer y cómo va a consumir su funcionalidad. La prueba ayudará a dar forma y moldear el sistema bajo prueba hasta que haya sido capaz de encapsular suficiente funcionalidad para satisfacer las tareas en las que esté trabajando.
Teniendo en cuenta el párrafo anterior, veamos sus preguntas:
- Si estoy usando una colección en mi sistema bajo prueba, estableceré una expectativa para asegurarme de que se invocó el código para insertar el elemento y luego afirmar el recuento de la colección. No necesariamente pruebo el método Add en mi lista interna. Solo me aseguro de que se haya llamado cuando se llama el método que agrega el elemento. Hago esto agregando un marco burlón en la mezcla, con mi marco de prueba.
- Probar cadenas como salida puede ser tedioso. No puedes dar cuenta de cada resultado. Solo puede probar lo que espera según la funcionalidad del sistema bajo prueba. Siempre debe dividir sus pruebas hasta el elemento más pequeño que está probando. Lo que significa que tendrás muchas pruebas, pero las pruebas son pequeñas y rápidas y solo prueban lo que deberían, nada más.
- Hay muchos frameworks de pruebas de código abierto para elegir. No voy a discutir cuál es el mejor. Solo encuentra uno que te guste y comienza a usarlo.
- Todo lo que puede hacer es configurar sus pruebas para dar cuenta de lo que quiere que suceda. Si aparece un escenario que introduce un error en su funcionalidad, al menos tiene una prueba sobre la funcionalidad para agregar ese escenario a la prueba y luego cambia su funcionalidad hasta que pase la prueba. Una forma de encontrar dónde nos hemos perdido una prueba es usar cobertura de código .
Te presenté al término burlón en la respuesta a la primera pregunta. Cuando introduce la burla en su arsenal para TDD, hace que las pruebas sean más fáciles de abstraer para extraer las partes que no son parte del sistema bajo prueba. Aquí hay algunos recursos sobre los marcos de burla que existen:
- Moq : Código abierto
- RhinoMocks : Código abierto
- TypeMock : Producto comercial
- NSustituto : Código abierto
Una forma de ayudar a usar TDD, además de leer sobre el proceso, es observar cómo la gente lo hace. Recomiendo ver las proyecciones de pantalla de JP Boodhoo en DNRTV . Mira esto:
- Jean Paul Boodhoo en desarrollo impulsado por prueba Parte 1
- Jean Paul Boodhoo en desarrollo impulsado por prueba parte 2
- Jean Paul Boodhoo sobre la desmitificación de patrones de diseño Parte 1
- Jean Paul Boodhoo sobre la desmitificación de patrones de diseño Parte 2
- Jean Paul Boodhoo sobre la desmitificación de patrones de diseño Parte 3
- Jean Paul Boodhoo sobre la desmitificación de patrones de diseño Parte 4
- Jean Paul Boodhoo sobre la desmitificación de patrones de diseño Parte 5
De acuerdo, esto te ayudará a ver cómo se usan los términos que introduje. También presentará otra herramienta llamada Resharper y cómo puede facilitar el proceso TDD. No podría recomendar esta herramienta lo suficiente al hacer TDD. Parece que está aprendiendo el proceso y que acaba de encontrar algunos de los problemas que ya se han solucionado con el uso de otras herramientas.
Creo que estaría haciendo una injusticia a la comunidad, si no actualizo esto agregando la nueva serie de Kent Beck en Test Driven Development en Pragmatic Programmer .