Pregunta

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

  • ¿Qué es?
  • ¿Qué hace por mí?
  • ¿Por qué debería usarlo?
  • ¿Cuándo debo usarlo (también cuándo no)?
  • ¿Cuáles son algunos errores y conceptos erróneos comunes?
¿Fue útil?

Solución

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

  • La ejecución de las pruebas se vuelve automatizable y repetible.
  • Puede realizar pruebas 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 categoriza más apropiadamente como una prueba de integración.Las pruebas de integración son algo bueno, pero no deben confundirse con las pruebas unitarias.El código de prueba unitaria debe ser breve, sencillo y rápido de ejecutar.

Otra forma de ver las pruebas unitarias es escribir las pruebas primero.Esto se conoce como desarrollo basado en pruebas (TDD, por sus siglas en inglés).TDD aporta ventajas adicionales:

  • No escribes código especulativo del tipo "Podría necesitar esto en el futuro", solo lo suficiente para que las pruebas pasen.
  • El código que has escrito siempre está cubierto por 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á realizando pruebas unitarias ahora, le recomiendo que comience con ellas.Consiga un buen libro, prácticamente cualquier libro xUnit servirá porque los conceptos son muy transferibles entre ellos.

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


Editar:Me viene a la mente un concepto erróneo, 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.Escribir las pruebas no solo suele acelerar el desarrollo, sino que también le brinda un indicador conveniente de "ya terminé" que de otra manera no tendría.

Otros consejos

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

La prueba unitaria es 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 el cambio de la implementación técnica y, al mismo tiempo, asegúrese de no cambiar el comportamiento (refactorización).El código correctamente probado por unidad se puede refactorizar/limpiar agresivamente con pocas posibilidades de romper algo sin darnos cuenta.
  2. Brinde confianza a los desarrolladores al agregar comportamientos o realizar correcciones.
  3. Documenta tu código
  4. Indique áreas de su código que estén estrechamente acopladas.Es difícil realizar una prueba unitaria de un código que está estrechamente acoplado
  5. Proporcione un medio para utilizar su API y buscar dificultades desde el principio
  6. Indica métodos y clases que no son muy cohesivos.

Debe realizar pruebas unitarias porque le conviene entregar un producto de calidad y mantenible a su cliente.

Le sugiero que lo use 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 programas utilitarios o desechables.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 no siempre es así)

El mayor peligro es que los desarrolladores prueben una unidad demasiado grande o consideren un método como una unidad.Esto es particularmente cierto si no entiendes Inversión de control - en cuyo caso sus pruebas unitarias siempre se convertirán en pruebas de integración de un extremo a otro.La prueba unitaria debe probar comportamientos individuales, y la mayoría de los métodos tienen muchos comportamientos.

El mayor error es pensar que los programadores no deberían realizar pruebas.Sólo los programadores malos o perezosos creen eso.¿El tipo que construye tu techo no debería probarlo?¿El médico que reemplaza una válvula cardíaca no debería probar la nueva válvula?Sólo 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: ¿hace el código?). lo que el cliente pagó para que hiciera)

La principal diferencia de las pruebas unitarias, a diferencia de "simplemente abrir un nuevo proyecto y probar este código específico" es que automatizado, de este modo 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 le hiciste una ligera modificación?¿Está dispuesto a volver a probarlo manualmente siempre que cualquier cosa ¿Cambios en tu código?Probablemente no :-(

Pero si puedes ejecute sus pruebas en cualquier momento, con un solo clic, exactamente de la misma manera, en unos pocos segundos, entonces ellos voluntad mostrarle inmediatamente cada vez que algo se rompe.Y si también integra las pruebas unitarias en su proceso de compilación automatizado, le alertarán sobre errores incluso en los casos en los que un cambio aparentemente sin ninguna relación rompió algo en una parte distante del código base, cuando ni siquiera se le ocurriría que hay Es necesario volver a probar esa funcionalidad en particular.

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

  • pruebas unitarias acortar el ciclo de retroalimentación del desarrollo dramáticamente:con un departamento de pruebas independiente, pueden pasar semanas hasta que sepa que hay un error en su código, momento en el cual ya habrá olvidado gran parte del contexto, por lo que puede llevarle horas encontrar y corregir 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, mierda, olvidé verificar esa condición aquí" :-)
  • pruebas unitarias de manera efectiva documento (su comprensión de) el comportamiento de su código
  • Las pruebas unitarias lo obligan a reevaluar sus opciones de diseño, lo que resulta en diseño más simple y limpio

Los marcos de pruebas unitarias, a su vez, le facilitan la escritura y ejecución de sus pruebas.

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

Me llevó bastante más tiempo comprender realmente 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 y pasas a la siguiente tarea.Nueve meses después y dos versiones después, alguien más hace un cambio en alguna aparentemente parte 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, es posible que ni siquiera conozcan tu módulo. existe.

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

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

Aportando las ventajas filosóficas de las pruebas unitarias y TDD, aquí hay algunas de las observaciones clave que me llamaron la atención en mis primeros pasos tentativos en el camino hacia la iluminación de TDD (ninguna original ni necesariamente noticias)...

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

  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 que puede dejar de realizar ajustes 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 tener errores o tener errores.Su PRUEBA podría tener errores o tener errores.En TDD, usted confía en que las posibilidades de que AMBOS sean malos o con errores sean bastante bajas.A menudo es la prueba la que necesita corrección, pero sigue siendo un buen resultado.

  4. TDD ayuda a codificar el estreñimiento.¿Conoces esa sensación de que tienes tanto que hacer que apenas sabes por dónde empezar?Es viernes por la tarde, si pospones las cosas 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 avance rápidamente.Además, al igual que las ratas de laboratorio, creo que todos respondemos a esa gran luz verde y trabajamos más duro para volver a verla.

  5. De manera similar, estos tipos de diseñadores pueden VER en qué están trabajando.Pueden alejarse para tomar un jugo, un cigarrillo o un iPhone y regresar a un monitor que inmediatamente les da una señal visual de adónde llegaron.TDD nos ofrece 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".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 está 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 algo, pueden ayudarle a migrar código de un proyecto a otro y brindarle una sensación injustificada de superioridad sobre sus colegas que no realizan pruebas :)

Esta presentación es una excelente introducción a todo lo delicioso que implican las pruebas de bondad.

Me gustaría recomendar el libro xUnit Testing Patterns de Gerard Meszaros.Es grande pero es un gran recurso para pruebas unitarias.Aquí hay un enlace a su sitio web donde analiza los conceptos básicos de las pruebas unitarias. http://xunitpatterns.com/XUnitBasics.html

Utilizo pruebas unitarias para ahorrar tiempo.

Al crear una funcionalidad de prueba de lógica empresarial (o acceso a datos), a menudo puede implicar escribir cosas en muchas pantallas que pueden estar terminadas o no todavía.Automatizar estas pruebas ahorra tiempo.

Para mí, las pruebas unitarias son una especie de arnés de prueba modularizado.Suele haber al menos una prueba por función pública.Escribo pruebas adicionales para cubrir diversos comportamientos.

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

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

Para las pruebas de acceso a datos, intento escribir pruebas que no tengan cambios o que se limpien por sí solas.

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.

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 empezó con unidad j en el mundo Java y se ha convertido en una mejor práctica en PHP también con Prueba simple y Unidad php.Es una práctica fundamental de la programación extrema y le ayuda a asegurarse de que su software siga funcionando según lo previsto después de la edición.Si tiene suficiente cobertura de pruebas, puede realizar refactorizaciones importantes, corregir errores o agregar funciones rápidamente con mucho menos temor de introducir otros problemas.

Es más eficaz cuando todas las pruebas unitarias se pueden ejecutar 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 afirmaciones, 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 con 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, en mi opinión, es mucho más fácil de poner en funcionamiento.En combinación con xDebug, phpUnit puede brindarle estadísticas automatizadas para la cobertura del código que algunas personas encuentran muy útiles.

Algunos equipos escriben enlaces desde su repositorio de subversion para que las pruebas unitarias se ejecuten automáticamente cada vez que confirma cambios.

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

Bibliotecas como Unidad N, xUnidad o unidad conjunta son simplemente obligatorios si deseas desarrollar tus proyectos usando el TDD enfoque popularizado por Kent Beck:

Puedes leer Introducción al desarrollo basado en pruebas (TDD) o el libro de Kent Beck Desarrollo basado en pruebas:Por ejemplo.

Luego, si desea asegurarse de que sus pruebas cubran una parte "buena" de su código, puede utilizar software como NCover, Jportada, PiezaCubierta o lo que sea.Te dirán el porcentaje de cobertura de tu código.Dependiendo de qué tan experto seas en TDD, sabrás si lo has practicado lo suficientemente bien :)

La prueba unitaria es la prueba de una unidad de código (p. ej.una sola función) sin la necesidad de la infraestructura de la que depende 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ías si fuera una prueba de integración, pero en este caso no lo es.

Por lo tanto, una prueba unitaria ejercería la funcionalidad incluida en la "función" que está probando sin 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é estás intentando probar aquí?¿Que la desviación estándar se calcula correctamente o que los datos se devuelven desde la base de datos?

En una prueba unitaria solo desea probar 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.

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

El Unidad parte del nombre tiene que ver con 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 estas pruebas; son marcos que ayudan con esto.Parte de eso son los ejecutores de pruebas automatizados que le indican qué pruebas fallan y cuáles pasan.

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

Puede realizar una prueba para comprobar que se ha producido una excepción esperada, sin tener que escribir usted mismo todo el bloque try catch.

Creo que el punto que no entiendes es que los marcos de pruebas unitarias como NUnit (y similares) te ayudarán en automatizando Pruebas de tamaño pequeño a mediano.Por lo general, puede ejecutar las pruebas en una GUI (ese es el caso con Unidad N, por ejemplo) simplemente haciendo clic en un botón y luego, con suerte, verás que la barra de progreso permanece verde.Si se vuelve rojo, el marco le muestra qué prueba falló y qué salió mal exactamente.En una prueba unitaria normal, a menudo se utilizan afirmaciones, p. Assert.AreEqual(expectedValue, actualValue, "some description") - Entonces, si los dos valores no son iguales, verá un error que dice "alguna descripción:esperado <valor esperado> pero era <valor actual>".

Entonces, 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 enviar código nuevo para no interrumpir el proceso de compilación de otros desarrolladores en el mismo proyecto.

Usar testículo.Todo lo que necesitas saber está ahí :)

Las pruebas unitarias son una práctica para asegurarse de que la función o módulo que va a implementar se comporte 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.

xUnidad, Unidad N, mbUnidad, etc.son herramientas que le ayudarán a redactar los exámenes.

Test Driven Development se ha apoderado del término prueba unitaria.Como veterano, mencionaré la definición más genérica del mismo.

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

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

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

Asistí a una presentación sobre pruebas unitarias en FoxForward 2007 y me dijeron que nunca hiciera pruebas unitarias de nada que funcionara con datos.Después de todo, si prueba con datos en vivo, los resultados son impredecibles y si no prueba con 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 hoy en día.:-)

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

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

¿Qué haces si te dan un montón de basura y parece que estás atrapado en un perpetuo estado de limpieza que sabes 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 poco a poco.El proyecto en el que acabo de entrar no tuvo 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 estamos por encima del 40% y hemos logrado recoger la mayor parte de la fruta madura.

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

Esto responde por qué debería realizar pruebas unitarias.


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

Examen de la unidad:Los minutos ahora ahorrarán horas después - Eric Mann - https://www.youtube.com/watch?v=_UmmaPe8Bzc

Pruebas unitarias JS (muy buenas) - https://www.youtube.com/watch?v=-IYqgx8JxlU

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


Ahora estoy aprendiendo sobre el tema, por lo que puede 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 se escribe un código de prueba (que se mantiene separado de su código principal) que llama a una función en su código principal con la entrada (argumentos) que la función requiere y el código luego verifica si obtiene un valor de retorno válido.Si obtiene un valor válido, el marco de pruebas unitarias 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 de inmediato. lance el nuevo código a producción; sin probarlo, es posible que no haya detectado 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 necesita modificar la función en su código principal, porque antes ya había escrito un código de prueba para esa función, ahora 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 debe devolver esa función.Nuevamente, sin la prueba realizada, ese error podría 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 utiliza algún script en una página web y funciona muy bien para su nuevo propósito previsto.Pero, también digamos, por el bien de los argumentos, que hay otra función que tiene en otra parte de su código que depende de esa función recién modificada para que funcione correctamente.Es posible que esta función dependiente ahora deje de funcionar debido a los cambios que realizó en la primera función; sin embargo, sin pruebas realizadas que su computadora ejecute automáticamente, no notará que hay un problema con esa función hasta que realmente se ejecute y Tendrás que navegar manualmente a una página web que incluye el script que ejecuta la función dependiente, solo entonces notarás que hay un error debido al cambio que realizaste en la primera función.

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


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

Además, no es necesario que realice una prueba unitaria de su código si no lo desea, pero vale la pena a medida que su proyecto/base de código comienza a crecer a medida que aumentan las posibilidades de introducir errores.

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 incrementalmente todo lo que escribe.Esto aumenta mucho la calidad del código, como verá inmediatamente, donde puede haber errores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top