¿Qué es la prueba unitaria? [cerrado]


211

Vi muchas preguntas que preguntaban "cómo" hacer una prueba unitaria en un idioma específico, pero ninguna pregunta preguntaba "qué", "por qué" y "cuándo".

  • ¿Qué es?
  • ¿Qué hace por mi?
  • ¿Por qué debería usarlo?
  • ¿Cuándo debería usarlo (también cuando no)?
  • ¿Cuáles son algunas trampas e ideas falsas comunes?

Uber, hay muchos recursos disponibles, y el artículo de Wikipedia es sin duda un excelente lugar para comenzar. Una vez que tenga una idea básica, tal vez algunas preguntas más específicas pueden ayudarlo a decidir por sí mismo si desea utilizar las pruebas unitarias.
palehorse

Código limpio conversaciones: youtube.com/watch?v=wEhu57pih5w
Kieran

1
Esa no es una pregunta específica. Eso son 5 preguntas generales.
Raedwald

99
Es bueno que haya hecho esta pregunta, leer la respuesta de un programador que trabaja es mucho mejor y hasta el punto en comparación con la lectura de recursos en línea.
Pratyush Dhanuka

Respuestas:


197

Las pruebas unitarias son, en términos generales, probar bits de su código de forma aislada con el código de prueba. Las ventajas inmediatas que vienen a la mente son:

  • La ejecución de las pruebas se vuelve automatizable y repetible
  • Puede probar a un nivel mucho más granular que las pruebas de apuntar y hacer clic a través de una GUI

Tenga en cuenta que si su código de prueba escribe en un archivo, abre una conexión de base de datos o hace algo a través de la red, se clasifica más apropiadamente como una prueba de integración. Las pruebas de integración son buenas, pero no deben confundirse con las pruebas unitarias. El código de prueba de la unidad debe ser corto, dulce y rápido de ejecutar.

Otra forma de ver las pruebas unitarias es escribir primero las pruebas. Esto se conoce como Test-Driven Development (TDD para abreviar). TDD trae ventajas adicionales:

  • No escribes el código especulativo "Podría necesitar esto en el futuro", solo lo suficiente para que las pruebas pasen
  • El código que ha escrito siempre está cubierto por las pruebas.
  • Al escribir la prueba primero, se ve obligado a pensar en cómo desea llamar al código, lo que generalmente mejora el diseño del código a largo plazo.

Si no está haciendo pruebas unitarias ahora, le recomiendo que comience a hacerlo. Obtenga un buen libro, prácticamente cualquier xUnit-book servirá porque los conceptos son muy transferibles entre ellos.

A veces, escribir pruebas unitarias puede ser doloroso. Cuando sea así, intenta encontrar a alguien que te ayude y resiste la tentación de "escribir el maldito código". Las pruebas unitarias se parecen mucho a lavar los platos. No siempre es agradable, pero mantiene limpia su cocina metafórica, y realmente desea que esté limpia. :)


Editar: Me viene a la mente un error, aunque no estoy seguro de si es tan común. Escuché a un gerente de proyecto decir que las pruebas unitarias hicieron que el equipo escribiera todo el código dos veces. Si se ve y se siente así, bueno, lo estás haciendo mal. No solo escribir las pruebas generalmente acelera el desarrollo, sino que también le brinda un conveniente indicador de "ahora que he terminado" que de otro modo no tendría.


2
¿Podría ampliar su punto de vista sobre cómo TDD acelera el desarrollo?
Martin

70

No estoy en desacuerdo con Dan (aunque una mejor opción puede ser simplemente no responder) ... pero ...

Las pruebas unitarias son el proceso de escribir código para probar el comportamiento y la funcionalidad de su sistema.

Obviamente, las pruebas mejoran la calidad de su código, pero eso es solo un beneficio superficial de las pruebas unitarias. Los beneficios reales son:

  1. Facilite cambiar la implementación técnica y asegúrese de no cambiar el comportamiento (refactorización). El código probado correctamente en la unidad se puede refactorizar / limpiar agresivamente con pocas posibilidades de romper algo sin darse cuenta.
  2. Brinde confianza a los desarrolladores al agregar comportamiento o hacer arreglos.
  3. Documenta tu código
  4. Indique las áreas de su código que están estrechamente acopladas. Es difícil probar el código de la unidad que está estrechamente acoplado
  5. Proporcione un medio para usar su API y buscar dificultades desde el principio
  6. Indica métodos y clases que no son muy coherentes.

Debe realizar una prueba unitaria porque le interesa entregar un producto mantenible y de calidad a su cliente.

Te sugiero que lo uses para cualquier sistema, o parte de un sistema, que modele el comportamiento del mundo real. En otras palabras, es particularmente adecuado para el desarrollo empresarial. No lo usaría para tirar / programas de utilidad. No lo usaría para partes de un sistema que son problemáticas de probar (la interfaz de usuario es un ejemplo común, pero ese no es siempre el caso)

La mayor dificultad es que los desarrolladores prueban una unidad demasiado grande, o consideran un método como una unidad. Esto es particularmente cierto si no comprende la Inversión de control , en cuyo caso las pruebas de su unidad siempre se convertirán en pruebas de integración de extremo a extremo. La prueba unitaria debe evaluar los comportamientos individuales, y la mayoría de los métodos tienen muchos comportamientos.

El mayor error es que los programadores no deberían probar. Solo los programadores malos o perezosos creen eso. ¿El tipo que construye tu techo no debería probarlo? ¿Debería el médico reemplazar una válvula cardíaca no probar la nueva válvula? Solo un programador puede probar que su código hace lo que pretendía que hiciera (el control de calidad puede probar casos extremos: cómo se comporta el código cuando se le dice que haga cosas que el programador no pretendía, y el cliente puede hacer una prueba de aceptación) lo que el cliente pagó por hacer)


44

La principal diferencia de las pruebas unitarias, en lugar de "simplemente abrir un nuevo proyecto y probar este código específico", es que está automatizado y , por lo tanto, es repetible .

Si prueba su código manualmente, puede convencerlo de que el código funciona perfectamente, en su estado actual . ¿Pero qué pasa una semana después, cuando hiciste una ligera modificación? ¿Estás dispuesto a volver a probarlo a mano cada vez que algo cambie en tu código? Lo más probable es que no :-(

Pero si puede ejecutar sus pruebas en cualquier momento, con un solo clic, exactamente de la misma manera, en unos pocos segundos , le mostrarán de inmediato cada vez que algo se rompa. Y si también integra las pruebas unitarias en su proceso de construcción automatizado, lo alertarán de errores incluso en casos en que un cambio aparentemente completamente relacionado rompió algo en una parte distante de la base de código, cuando ni siquiera se le ocurriría que hay una necesidad de volver a probar esa funcionalidad particular.

Esta es la principal ventaja de las pruebas unitarias sobre las pruebas manuales. Pero espera, hay más:

  • las pruebas unitarias acortan drásticamente el ciclo de retroalimentación de desarrollo : con un departamento de pruebas separado, puede llevar semanas saber que hay un error en su código, momento en el que ya ha olvidado gran parte del contexto, por lo que puede llevarle horas encuentra y arregla el error; OTOH con pruebas unitarias, el ciclo de retroalimentación se mide en segundos, y el proceso de corrección de errores suele ser similar a un "oh sh * t, olvidé verificar esa condición aquí" :-)
  • las pruebas unitarias documentan efectivamente (su comprensión de) el comportamiento de su código
  • las pruebas unitarias lo obligan a reevaluar sus elecciones de diseño, lo que resulta en un diseño más simple y limpio

Los marcos de pruebas unitarias, a su vez, le facilitan escribir y ejecutar sus pruebas.


+1 Además, mi parte favorita sobre el código de prueba (especialmente cuando se le da una nueva base de código): demuestra el uso esperado del código bajo prueba.
Steven Evers

34

Nunca me enseñaron las pruebas unitarias en la universidad, y me tomó un tiempo "obtenerlas". Lo leí, dije "ah, claro, pruebas automatizadas, eso podría ser genial, supongo", y luego me olvidé de eso.

Pasó bastante tiempo antes de que realmente entendiera el punto: Digamos que estás trabajando en un sistema grande y escribes un módulo pequeño. Se compila, lo pones a prueba, funciona muy bien, pasas a la siguiente tarea. Nueve meses después y dos versiones más tarde, alguien más hace un cambio en una parte aparentemente no relacionada del programa, y ​​rompe el módulo. Peor aún, prueban sus cambios y su código funciona, pero no prueban su módulo; Demonios, puede que ni siquiera sepan que tu módulo existe .

Y ahora tienes un problema: el código roto está en el tronco y nadie lo sabe. El mejor caso es que un probador interno lo encuentre antes de enviarlo, pero arreglar el código tan tarde en el juego es caro. Y si ningún probador interno lo encuentra ... bueno, eso puede ser muy costoso.

La solución son las pruebas unitarias. Detectarán problemas cuando escriba código, lo cual está bien, pero podría haberlo hecho a mano. La verdadera recompensa es que detectarán problemas nueve meses más adelante cuando ahora está trabajando en un proyecto completamente diferente, pero un pasante de verano cree que se vería más ordenado si esos parámetros estuvieran en orden alfabético, y luego la prueba unitaria escribió que el camino de regreso falla, y alguien arroja cosas al interno hasta que vuelva a cambiar el orden de los parámetros. Ese es el "por qué" de las pruebas unitarias. :-)


13

Incluyendo las ventajas filosóficas de las pruebas unitarias y TDD aquí hay algunas de sus observaciones clave de "bombilla" que me sorprendieron en mis primeros pasos tentativos en el camino hacia la iluminación de TDD (ninguno original o necesariamente noticias) ...

  1. TDD NO significa escribir el doble de la cantidad de código. El código de prueba suele ser bastante rápido y sencillo de escribir, y es una parte clave de su proceso de diseño y de manera crítica.

  2. ¡TDD te ayuda a darte cuenta de cuándo dejar de codificar! Sus pruebas le dan la confianza de que ha hecho lo suficiente por ahora y puede dejar de ajustar y pasar a lo siguiente.

  3. Las pruebas y el código trabajan juntos para lograr un mejor código. Su código podría ser malo / defectuoso. Su PRUEBA podría ser mala / con errores. En TDD está contando con las posibilidades de que AMBOS sean malos / que los errores sean bastante bajos. A menudo es la prueba la que necesita arreglarse, pero sigue siendo un buen resultado.

  4. TDD ayuda con la codificación del estreñimiento. ¿Sabes esa sensación de que tienes tanto que hacer que apenas sabes por dónde empezar? Es viernes por la tarde, si solo posterga un par de horas más ... TDD le permite desarrollar muy rápidamente lo que cree que necesita hacer, y hace que su codificación se mueva rápidamente. Además, al igual que las ratas de laboratorio, ¡creo que todos respondemos a esa gran luz verde y trabajamos más para volver a verla!

  5. De manera similar, estos tipos de diseñadores pueden VER en qué están trabajando. Pueden deambular por un descanso de jugo / cigarrillo / iphone y regresar a un monitor que les da inmediatamente una señal visual de dónde llegaron. TDD nos da algo similar. Es más fácil ver a dónde llegamos cuando la vida interviene ...

  6. Creo que fue Fowler quien dijo: "Las pruebas imperfectas, ejecutadas con frecuencia, son mucho mejores que las pruebas perfectas que nunca se escriben en absoluto". Interpreto que esto me da permiso para escribir pruebas donde creo que serán más útiles incluso si el resto de la cobertura de mi código es lamentablemente incompleta.

  7. TDD ayuda en todo tipo de formas sorprendentes en el futuro. Las buenas pruebas unitarias pueden ayudar a documentar lo que se supone que debe hacer, pueden ayudarlo a migrar el código de un proyecto a otro y brindarle una sensación injustificada de superioridad sobre sus colegas que no lo prueban :)

Esta presentación es una excelente introducción a todas las deliciosas pruebas de bondad.



5

Utilizo pruebas unitarias para ahorrar tiempo.

Cuando se construye la lógica de negocios (o el acceso a datos), la funcionalidad de prueba a menudo puede implicar escribir cosas en muchas pantallas que pueden o no estar terminadas todavía. La automatización de estas pruebas ahorra tiempo.

Para mí, las pruebas unitarias son un tipo de arnés de prueba modularizado. Por lo general, hay al menos una prueba por función pública. Escribo pruebas adicionales para cubrir varios comportamientos.

Todos los casos especiales que pensó al desarrollar el código pueden registrarse en el código en las pruebas unitarias. Las pruebas unitarias también se convierten en una fuente de ejemplos sobre cómo usar el código.

Es mucho más rápido para mí descubrir que mi nuevo código rompe algo en las pruebas de mi unidad y luego verificar el código y hacer que algún desarrollador front-end encuentre un problema.

Para las pruebas de acceso a datos, intento escribir pruebas que no hayan cambiado o que se limpien después de ellas.

Las pruebas unitarias no podrán resolver todos los requisitos de prueba. Podrán ahorrar tiempo de desarrollo y probar partes centrales de la aplicación.


4

Esta es mi opinión sobre ella. Yo diría que las pruebas unitarias son la práctica de escribir pruebas de software para verificar que su software real hace lo que debe hacer. Esto comenzó con jUnit en el mundo de Java y también se ha convertido en una práctica recomendada en PHP con SimpleTest y phpUnit . Es una práctica central de la Programación extrema y le ayuda a asegurarse de que su software todavía funciona como se esperaba después de la edición. Si tiene suficiente cobertura de prueba, puede realizar una refactorización importante, corregir errores o agregar funciones rápidamente con mucho menos temor de presentar otros problemas.

Es más efectivo cuando todas las pruebas unitarias pueden ejecutarse automáticamente.

Las pruebas unitarias generalmente se asocian con el desarrollo OO. La idea básica es crear un script que configure el entorno para su código y luego lo ejercite; usted escribe aserciones, especifica el resultado previsto que debe recibir y luego ejecuta su script de prueba utilizando un marco como los mencionados anteriormente.

El marco ejecutará todas las pruebas contra su código y luego informará el éxito o el fracaso de cada prueba. phpUnit se ejecuta desde la línea de comandos de Linux de forma predeterminada, aunque hay interfaces HTTP disponibles para ello. SimpleTest está basado en la web por naturaleza y es mucho más fácil de poner en marcha, en mi opinión. En combinación con xDebug, phpUnit puede proporcionarle estadísticas automatizadas para la cobertura de código que algunas personas consideran muy útiles.

Algunos equipos escriben ganchos desde su repositorio de subversión para que las pruebas unitarias se ejecuten automáticamente cada vez que se confirman cambios.

Es una buena práctica mantener sus pruebas unitarias en el mismo repositorio que su aplicación.


4

Las bibliotecas como NUnit , xUnit o JUnit son solo obligatorias si desea desarrollar sus proyectos utilizando el enfoque TDD popularizado por Kent Beck:

Puede leer Introducción al desarrollo impulsado por pruebas (TDD) o el libro de Kent Beck Test Driven Development: By Example .

Luego, si desea asegurarse de que sus pruebas cubran una parte "buena" de su código, puede usar software como NCover , JCover , PartCover o lo que sea. Le indicarán el porcentaje de cobertura de su código. Dependiendo de cuánto sea experto en TDD, sabrá si lo ha practicado lo suficientemente bien :)


3

La prueba de unidad es la prueba de una unidad de código (por ejemplo, una sola función) sin la necesidad de la infraestructura en la que se basa esa unidad de código. es decir, pruébelo de forma aislada.

Si, por ejemplo, la función que está probando se conecta a una base de datos y realiza una actualización, en una prueba unitaria, es posible que no desee realizar esa actualización. Lo haría si fuera una prueba de integración, pero en este caso no lo es.

Por lo tanto, una prueba unitaria ejercitaría la funcionalidad incluida en la "función" que está probando sin los efectos secundarios de la actualización de la base de datos.

Digamos que su función recuperó algunos números de una base de datos y luego realizó un cálculo de desviación estándar. ¿Qué intentas probar aquí? ¿Que la desviación estándar se calcula correctamente o que los datos se devuelven de la base de datos?

En una prueba unitaria solo desea comprobar que la desviación estándar se calcula correctamente. En una prueba de integración, desea probar el cálculo de la desviación estándar y la recuperación de la base de datos.


3

Las pruebas unitarias consisten en escribir código que pruebe el código de su aplicación.

La parte de Unidad del nombre trata sobre la intención de probar pequeñas unidades de código (un método, por ejemplo) a la vez.

xUnit está ahí para ayudar con esta prueba: son marcos que ayudan con esto. Parte de eso son los corredores de prueba automatizados que le dicen qué prueba falla y cuáles pasan.

También tienen facilidades para configurar el código común que necesita en cada prueba de antemano y desglosarlo cuando todas las pruebas hayan terminado.

Puede realizar una prueba para verificar que se haya producido una excepción esperada, sin tener que escribir todo el bloque try catch.


3

Creo que el punto que no comprende es que los marcos de pruebas unitarias como NUnit (y similares) lo ayudarán a automatizar las pruebas pequeñas a medianas. Por lo general, puede ejecutar las pruebas en una GUI (ese es el caso de NUnit , por ejemplo) simplemente haciendo clic en un botón y luego, con suerte, verá que la barra de progreso permanece verde. Si se vuelve rojo, el marco muestra qué prueba falló y qué salió mal exactamente. En una prueba de unidad normal, a menudo utiliza aserciones, por ejemplo, por Assert.AreEqual(expectedValue, actualValue, "some description")lo que si los dos valores son desiguales, verá un error que dice "alguna descripción: esperado <valor esperado> pero fue <valor real>".

Como conclusión, las pruebas unitarias harán que las pruebas sean más rápidas y mucho más cómodas para los desarrolladores. Puede ejecutar todas las pruebas unitarias antes de confirmar el nuevo código para no interrumpir el proceso de compilación de otros desarrolladores en el mismo proyecto.



3

La prueba unitaria es una práctica para asegurarse de que la función o módulo que va a implementar se comportará como se espera (requisitos) y también para asegurarse de cómo se comporta en escenarios como condiciones de contorno y entradas no válidas.

xUnit , NUnit , mbUnit , etc. son herramientas que lo ayudan a escribir las pruebas.


2

Test Driven Development ha asumido el término Test de Unidad. Como antiguo temporizador, mencionaré la definición más genérica del mismo.

Prueba de unidad también significa probar un solo componente en un sistema más grande. Este componente único podría ser un dll, exe, biblioteca de clases, etc. Incluso podría ser un sistema único en una aplicación multisistema. Entonces, en última instancia, Unit Test termina siendo la prueba de lo que quieras llamar una sola pieza de un sistema más grande.

Luego pasaría a las pruebas integradas o de sistema probando cómo todos los componentes funcionan juntos.


2

En primer lugar, ya sea que se trate de pruebas unitarias o de cualquier otro tipo de prueba automatizada (integración, carga, prueba de interfaz de usuario, etc.), la diferencia clave con respecto a lo que sugiere es que es automática, repetible y no requiere recursos humanos. para ser consumido (= nadie tiene que realizar las pruebas, generalmente se ejecutan con solo presionar un botón).


1

Fui a una presentación sobre pruebas unitarias en FoxForward 2007 y me dijeron que nunca probara algo que funcione con datos. Después de todo, si prueba en datos en vivo, los resultados son impredecibles, y si no prueba en datos en vivo, en realidad no está probando el código que escribió. Desafortunadamente, esa es la mayor parte de la codificación que hago en estos días. :-)

Probé TDD recientemente cuando estaba escribiendo una rutina para guardar y restaurar la configuración. Primero, verifiqué que podía crear el objeto de almacenamiento. Entonces, que tenía el método que necesitaba llamar. Entonces, que podría llamarlo. Entonces, que podría pasarle parámetros. Entonces, que podría pasarle parámetros específicos. Y así sucesivamente, hasta que finalmente verificara que guardaría la configuración especificada, permítame cambiarla y luego restaurarla para varias sintaxis diferentes.

No llegué al final, porque necesitaba la maldita rutina, pero fue un buen ejercicio.


1

¿Qué hacer si se le da un montón de basura y parece que está atrapado en un estado perpetuo de limpieza que sabe que con la adición de cualquier nueva característica o código puede romper el conjunto actual porque el software actual es como una casa de tarjetas?

¿Cómo podemos hacer pruebas unitarias entonces?

Empiezas pequeño. El proyecto en el que acabo de entrar no tenía pruebas unitarias hasta hace unos meses. Cuando la cobertura era tan baja, simplemente elegíamos un archivo que no tenía cobertura y hacíamos clic en "agregar pruebas".

En este momento, llegamos a más del 40%, y hemos logrado recoger la mayoría de las frutas bajas.

(La mejor parte es que, incluso con este bajo nivel de cobertura, ya nos hemos encontrado con muchas instancias del código haciendo lo incorrecto, y las pruebas lo detectaron. Eso es un gran motivador para impulsar a las personas a agregar más pruebas).


1

Esto responde por qué deberías estar haciendo pruebas unitarias.


Los 3 videos a continuación cubren las pruebas unitarias en javascript, pero los principios generales se aplican en la mayoría de los idiomas.

Pruebas de la unidad: los minutos ahora ahorrarán horas más tarde - Eric Mann - https://www.youtube.com/watch?v=_UmmaPe8Bzc

Prueba de unidad JS (muy buena) - https://www.youtube.com/watch?v=-IYqgx8JxlU

Escribir JavaScript comprobable: https://www.youtube.com/watch?v=OzjogCFO4Zo


Ahora solo estoy aprendiendo sobre el tema, por lo que es posible que no esté 100% correcto y hay más de lo que estoy describiendo aquí, pero mi comprensión básica de las pruebas unitarias es que escribes un código de prueba (que se mantiene separado de tu código principal) que llama a una función en su código principal con la entrada (argumentos) que requiere la función y luego el código verifica si recupera un valor de retorno válido. Si recupera un valor válido, el marco de prueba de la unidad que está utilizando para ejecutar las pruebas muestra una luz verde (todo bien) si el valor no es válido, obtiene una luz roja y luego puede solucionar el problema inmediatamente antes de libere el nuevo código a producción, sin probar es posible que no haya captado el error.

Entonces escribe pruebas para su código actual y crea el código para que pase la prueba. Meses después, usted u otra persona necesitan modificar la función en su código principal, porque antes ya había escrito el código de prueba para esa función, ahora se ejecuta nuevamente y la prueba puede fallar porque el codificador introdujo un error lógico en la función o devolvió algo por completo diferente de lo que se supone que devuelve esa función. Nuevamente, sin la prueba en su lugar, ese error puede ser difícil de rastrear, ya que posiblemente también pueda afectar a otro código y pasará desapercibido.


Además, el hecho de que tenga un programa de computadora que ejecute su código y lo pruebe en lugar de hacerlo manualmente en el navegador página por página ahorra tiempo (pruebas unitarias para javascript). Digamos que modifica una función que es utilizada por algún script en una página web y funciona muy bien para su nuevo propósito. Pero, digamos también por razones de argumentos, que hay otra función que tiene en otro lugar de su código que depende de esa función recién modificada para que funcione correctamente. Esta función dependiente ahora puede dejar de funcionar debido a los cambios que ha realizado en la primera función, sin embargo, sin las pruebas que se ejecutan automáticamente en su computadora, no notará que hay un problema con esa función hasta que realmente se ejecute y tú'

Para reiterar, tener pruebas que se ejecutan mientras se desarrolla su aplicación detectará este tipo de problemas a medida que codifica. Al no tener las pruebas en su lugar, tendría que revisar manualmente toda su aplicación e incluso entonces puede ser difícil detectar el error, ingenuamente lo envía a producción y después de un tiempo un usuario amable le envía un informe de error no será tan bueno como sus mensajes de error en un marco de prueba).


Es bastante confuso cuando escuchas por primera vez sobre el tema y piensas para ti mismo, ¿no estoy probando mi código? Y el código que ha escrito funciona como se supone que debe hacerlo, "¿por qué necesito otro marco?" ... Sí, ya está probando su código, pero una computadora es mejor para hacerlo. Solo tiene que escribir pruebas lo suficientemente buenas para una función / unidad de código una vez y el resto se encarga de usted por la poderosa CPU en lugar de tener que verificar manualmente que todo su código todavía funciona cuando realiza un cambio en tu codigo.

Además, no tiene que probar el código de la unidad si no lo desea, pero vale la pena a medida que su base de proyecto / código comienza a crecer a medida que aumentan las posibilidades de introducir errores.


0

Las pruebas unitarias y TDD en general le permiten tener ciclos de retroalimentación más cortos sobre el software que está escribiendo. En lugar de tener una gran fase de prueba al final de la implementación, prueba gradualmente todo lo que escribe. Esto aumenta mucho la calidad del código, como puede ver de inmediato, donde podría tener errores.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.