¿Qué tan profundo son sus pruebas unitarias?


Lo que he encontrado acerca de TDD es que su toma tiempo para obtener sus pruebas de configuración y ser naturalmente perezoso siempre quiero escribir el menor código posible. Lo primero que parece hacer es probar que mi constructor ha establecido todas las propiedades, pero ¿es esto excesivo?

Mi pregunta es ¿a qué nivel de granularidad escribes tus pruebas unitarias?

..¿y hay un caso de pruebas demasiado?

Author: Mihai Limbășan, 2008-09-30

17 answers

Me pagan por código que funciona, no por pruebas, por lo que mi filosofía es probar lo menos posible para alcanzar un determinado nivel de confianza (sospecho que este nivel de confianza es alto en comparación con los estándares de la industria, pero eso podría ser arrogancia). Si normalmente no cometo un tipo de error (como establecer las variables incorrectas en un constructor), no lo pruebo. Tiendo a dar sentido a los errores de prueba, así que soy muy cuidadoso cuando tengo lógica con condicionales complicados. Al codificar en un equipo, modifico mi estrategia para probar cuidadosamente el código que, colectivamente, tendemos a equivocarnos.

Diferentes personas tendrán diferentes estrategias de prueba basadas en esta filosofía, pero eso me parece razonable dado el estado inmaduro de comprensión de cómo las pruebas pueden encajar mejor en el bucle interno de la codificación. Dentro de diez o veinte años probablemente tendremos una teoría más universal de qué pruebas escribir, qué pruebas no escribir, y cómo distinguir la diferencia. Mientras tanto, la experimentación parece estar en orden.

 221
Author: Kent Beck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 15:30:47

Escribe pruebas unitarias para cosas que esperas romper y para casos extremos. Después de eso, se deben agregar casos de prueba a medida que llegan los informes de errores, antes de escribir la corrección del error. El desarrollador puede entonces estar seguro de que:

  1. El error está solucionado;
  2. El error no volverá a aparecer.

Por el comentario adjunto - Supongo que este enfoque para escribir pruebas unitarias podría causar problemas, si se descubren muchos errores, con el tiempo, en una clase dada. Esto es probablemente donde la discreción es útil-agregar pruebas unitarias solo para errores que es probable que vuelvan a ocurrir, o donde su repetición causaría problemas graves. He encontrado que una medida de las pruebas de integración en las pruebas unitarias puede ser útil en estos escenarios: probar código de rutas de código superiores puede cubrir las rutas de código inferiores.

 20
Author: Dominic Rodger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 17:45:23

Todo debe hacerse tan simple como posible, pero no más simple. - A. Einstein

Una de las cosas más incomprendidas acerca de TDD es la primera palabra en ella. Prueba. Por eso vino BDD. Porque la gente realmente no entendía que la primera D era la importante, es decir, Impulsada. Todos tendemos a pensar un poco en las pruebas, y un poco en la conducción del diseño. Y supongo que esta es una respuesta vaga a su pregunta, pero usted probablemente debería considerar cómo manejar su código, en lugar de lo que realmente está probando; eso es algo con lo que una herramienta de cobertura puede ayudarlo. El diseño es un tema bastante más grande y problemático.

 19
Author: kitofr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:26:39

Para aquellos que proponen probar "todo": se dan cuenta de que "probar completamente" un método como int square(int x) requiere alrededor de 4 mil millones de casos de prueba en lenguajes comunes y entornos típicos.

De hecho, es incluso peor que eso: un método void setX(int newX) también está obligado no a alterar los valores de cualquier otro miembro además de x are obj.y, obj.z, etc. todos permanecen sin cambios después de llamar obj.setX(42);?

Solo es práctico probar un subconjunto de "todo." Una vez que aceptas esto, se vuelve más aceptable considerar no probar un comportamiento increíblemente básico. Cada programador tiene una distribución de probabilidad de ubicaciones de errores; el enfoque inteligente es enfocar su energía en regiones de prueba donde estima que la probabilidad de error es alta.

 15
Author: j_random_hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-17 05:29:44

La respuesta clásica es "probar cualquier cosa que pueda romperse". Interpreto eso como significando que probar a los setters y getters que no hacen nada excepto set o get es probablemente demasiada prueba, no hay necesidad de tomarse el tiempo. A menos que tu IDE los escriba para ti, entonces podrías también.

Si su constructor no establecer propiedades podría conducir a errores más adelante, entonces probar que están configuradas no es exagerado.

 9
Author: Dennis S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:23:13

Escribo pruebas para cubrir los supuestos de las clases que escribiré. Las pruebas hacen cumplir los requisitos. Esencialmente, si x nunca puede ser 3, por ejemplo, voy a asegurar que hay una prueba que cubre ese requisito.

Invariablemente, si no escribo una prueba para cubrir una condición, aparecerá más tarde durante la prueba "humana". Ciertamente escribiré uno entonces, pero prefiero cogerlos temprano. Creo que el punto es que las pruebas son tediosas (quizás) pero necesarias. Escribo suficientes pruebas para ser completa, pero no más que eso.

 5
Author: itsmatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:38:35

Parte del problema con omitir pruebas simples ahora es que en el futuro la refactorización podría hacer que esa propiedad simple sea muy complicada con mucha lógica. Creo que la mejor idea es que puede usar Pruebas para verificar los requisitos del módulo. Si cuando pasas X debes recuperar Y, entonces eso es lo que quieres probar. Luego, cuando cambie el código más adelante, puede verificar que X le da Y, y puede agregar una prueba para A le da B, cuando ese requisito se agrega más adelante.

He descubrí que el tiempo que paso durante el desarrollo inicial escribiendo pruebas vale la pena en la primera o segunda corrección de errores. La capacidad de recoger el código que no ha mirado en 3 meses y estar razonablemente seguro de que su corrección cubre todos los casos, y "probablemente" no rompe nada es enormemente valioso. También encontrará que las pruebas unitarias ayudarán a clasificar errores mucho más allá del seguimiento de la pila, etc. Ver cómo las piezas individuales de la aplicación funcionan y fallan da una gran idea de por qué funcionan o fallan en su conjunto.

 5
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 15:26:17

En la mayoría de los casos, yo diría, si hay lógica allí, probarlo. Esto incluye constructores y propiedades, especialmente cuando más de una cosa se establece en la propiedad.

Con respecto a demasiadas pruebas, es discutible. Algunos dirían que todo debe ser probado para la robustez, otros dicen que para pruebas eficientes, solo las cosas que podrían romperse (es decir, la lógica) deben ser probadas.

Me inclinaría más hacia el segundo campamento, solo por experiencia personal, pero si alguien decidí probar todo, no diría que era demasiado... un poco exagerado tal vez para mí, pero no demasiado para ellos.

Por lo tanto, No - yo diría que no hay tal cosa como "demasiado" pruebas en el sentido general, solo para los individuos.

 4
Author: Fry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 15:46:59

El desarrollo basado en pruebas significa que usted deja de codificar cuando todas sus pruebas pasan.

Si no tiene ninguna prueba para una propiedad, entonces ¿por qué debería implementarla? Si no prueba / define el comportamiento esperado en caso de una asignación "ilegal", ¿qué debe hacer la propiedad?

Por lo tanto, estoy totalmente a favor de probar cada comportamiento que una clase debe exhibir. Incluyendo propiedades "primitivas".

Para hacer esta prueba más fácil, he creado un NUnit simple TestFixture que proporciona extensión puntos para establecer / obtener el valor y toma listas de valores válidos e inválidos y tiene una única prueba para verificar si la propiedad funciona correctamente. Probar una sola propiedad podría tener este aspecto:

[TestFixture]
public class Test_MyObject_SomeProperty : PropertyTest<int>
{

    private MyObject obj = null;

    public override void SetUp() { obj = new MyObject(); }
    public override void TearDown() { obj = null; }

    public override int Get() { return obj.SomeProperty; }
    public override Set(int value) { obj.SomeProperty = value; }

    public override IEnumerable<int> SomeValidValues() { return new List() { 1,3,5,7 }; }
    public override IEnumerable<int> SomeInvalidValues() { return new List() { 2,4,6 }; }

}

Usando lambdas y atributos esto podría incluso escribirse de manera más compacta. Deduzco que MbUnit tiene incluso algo de soporte nativo para cosas como esa. Sin embargo, el punto es que el código anterior captura la intención de la propiedad.

P.d.: Probablemente la prueba de propiedad también debería tener una forma de comprobar que otras propiedades en el objeto no han cambiado. Hmm .. de vuelta a la mesa de dibujo.

 3
Author: David Schmitt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 15:27:58

Hago pruebas unitarias para alcanzar la máxima cobertura posible. Si no puedo alcanzar algún código, refactorizo hasta que la cobertura esté lo más completa posible

Después de terminar la prueba de escritura cegadora, generalmente escribo un caso de prueba reproduciendo cada error

Estoy acostumbrado a separar entre las pruebas de código y las pruebas de integración. Durante las pruebas de integración, (que también son pruebas unitarias, pero en grupos de componentes, por lo que no es exactamente para lo que son las pruebas unitarias) Probaré los requisitos para ser implementado correctamente.

 1
Author: Lorenzo Boccaccia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:47:41

Así que cuanto más conduzco mi programación escribiendo pruebas, menos me preocupo por el nivel de granualidad de las pruebas. Mirando hacia atrás, parece que estoy haciendo lo más simple posible para lograr mi objetivo de validar el comportamiento . Esto significa que estoy generando una capa de confianza de que mi código está haciendo lo que pido, sin embargo, esto no se considera una garantía absoluta de que mi código esté libre de errores. Creo que el equilibrio correcto es probar el comportamiento estándar y tal vez un caso de borde o dos a continuación, pasar a la siguiente parte de mi diseño.

Acepto que esto no cubrirá todos los errores y uso otros métodos de prueba tradicionales para capturarlos.

 1
Author: Johnno Nolan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-28 12:39:25

Generalmente, empiezo pequeño, con entradas y salidas que sé que deben funcionar. Luego, a medida que corrijo errores, agrego más pruebas para asegurar que las cosas que he corregido se prueben. Es orgánico, y funciona bien para mí.

¿Puedes probar demasiado? Probablemente, pero probablemente sea mejor errar por el lado de la precaución en general, aunque dependerá de cuán crítica sea la misión de su aplicación.

 0
Author: Tim Sullivan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:25:10

Creo que debes probar todo en tu "núcleo" de la lógica de tu negocio. Getter y Setter también porque podrían aceptar valor negativo o valor nulo que usted podría no querer aceptar. Si tienes tiempo (siempre depende de tu jefe)es bueno probar otra lógica de negocios y todos los controladores que llaman a estos objetos (vas de la prueba unitaria a la prueba de integración lentamente).

 0
Author: Patrick Desjardins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:27:48

No hago pruebas unitarias métodos simples de setter/getter que no tienen efectos secundarios. Pero hago pruebas unitarias de todos los demás métodos públicos. Intento crear pruebas para todas las condiciones de contorno en mis algoritmos y comprobar la cobertura de mis pruebas unitarias.

Es mucho trabajo, pero creo que vale la pena. Prefiero escribir código (incluso el código de prueba) que pasar por el código en un depurador. Encuentro que el ciclo de código-compilación-implementación-depuración consume mucho tiempo y cuanto más exhaustivas son las pruebas unitarias que he integrado en mi compilación, menos tiempo paso pasando por ese ciclo de compilación, implementación y depuración de código.

Usted no dijo por qué la arquitectura que está codificando demasiado. Pero para Java puedo usar Maven 2, JUnit, DbUnit, Cobertura, & EasyMock.

 0
Author: Brian Matthews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 14:31:02

Cuanto más leo sobre él, más creo que algunas pruebas unitarias son como algunos patrones: Un olor a idiomas insuficientes.

Cuando necesita probar si su getter trivial realmente devuelve el valor correcto, es porque puede mezclar el nombre del getter y el nombre de la variable miembro. Introduzca 'attr_reader: name' de ruby, y esto no puede suceder más. Simplemente no es posible en Java.

Si su getter alguna vez se vuelve no trivial, todavía puede agregar una prueba para él entonces.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-06 18:54:22

Prueba el código fuente que te preocupa.

No es útil para probar porciones de código en las que se tiene mucha confianza, siempre y cuando no se cometan errores en él.

Pruebe las correcciones de errores, de modo que sea la primera y la última vez que corrija un error.

Prueba para obtener confianza de partes de código oscuras, para que crees conocimiento.

Pruebe antes de la refactorización pesada y media, para que no rompa las características existentes.

 0
Author: castle1971,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-17 12:09:19

Esta respuesta es más para averiguar cuántas pruebas unitarias usar para un método dado que sabe que desea realizar pruebas unitarias debido a su criticidad/importancia. Usando la técnica Basis Path Testing de McCabe, podría hacer lo siguiente para tener cuantitativamente mejor confianza en la cobertura del código que una simple "cobertura de declaración"o" cobertura de rama":

  1. Determine el valor de Complejidad ciclomática de su método que desea probar unitariamente (Visual Studio 2010 Ultimate, por ejemplo, puede calcule esto por usted con herramientas de análisis estático; de lo contrario, puede calcularlo a mano a través del método flowgraph - http://users.csc.calpoly.edu / ~jdalbey/206/Lectures/BasisPathTutorial/index.html)
  2. Enumere el conjunto básico de rutas independientes que fluyen a través de su método-consulte el enlace anterior para ver el ejemplo de flowgraph
  3. Preparar ensayos unitarios para cada surco de base independiente determinado en la etapa 2
 0
Author: J.D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-09 03:33:27