Articulo de referencia

Pruebas unitarias

Las pruebas unitarias , también conocidas como pruebas de componentes o módulos , son una forma de prueba de software mediante la cual se prueba código fuente aislado para valid...

Las pruebas unitarias , también conocidas como pruebas de componentes o módulos , son una forma de prueba de software mediante la cual se prueba código fuente aislado para validar el comportamiento esperado. [ 1 ]

Las pruebas unitarias describen las pruebas que se ejecutan a nivel de unidad para contrastar con las pruebas a nivel de integración o de sistema . [ 2 ]

Historia

Las pruebas unitarias, como principio para probar por separado partes más pequeñas de grandes sistemas de software, se remontan a los inicios de la ingeniería de software. En junio de 1956, en el Simposio de la Marina de los EE. UU. sobre Métodos Avanzados de Programación para Computadoras Digitales, HD Benington presentó el proyecto SAGE . Este proyecto se caracterizaba por un enfoque basado en especificaciones, donde la fase de codificación iba seguida de una "prueba de parámetros" para validar los subprogramas componentes según su especificación, seguida luego de una "prueba de ensamblaje" para las partes ensambladas. [ 3 ] [ 4 ]

En 1964, se describe un enfoque similar para el software del proyecto Mercury , donde las unidades individuales desarrolladas por diferentes programadores se sometieron a "pruebas unitarias" antes de integrarse. [ 5 ] En 1969, las metodologías de prueba parecen más estructuradas, con pruebas unitarias, pruebas de componentes y pruebas de integración que validan colectivamente las partes individuales escritas por separado y su ensamblaje progresivo en bloques más grandes. [ 6 ] Algunos estándares públicos adoptados a finales de la década de 1960, como MIL-STD-483 [ 7 ] y MIL-STD-490, contribuyeron aún más a una amplia aceptación de las pruebas unitarias en grandes proyectos.

En aquella época, las pruebas unitarias eran interactivas [ 4 ] o automatizadas [ 8 ] , utilizando pruebas codificadas o herramientas de captura y reproducción de pruebas. En 1989, Kent Beck describió un marco de pruebas para Smalltalk (más tarde llamado SUnit ) en "Simple Smalltalk Testing: With Patterns". En 1997, Kent Beck y Erich Gamma desarrollaron y publicaron JUnit , un marco de pruebas unitarias que se popularizó entre los desarrolladores de Java [ 9 ] . Google adoptó las pruebas automatizadas alrededor de 2005-2006 [ 10 ] .

Unidad

Una unidad se define como un comportamiento único exhibido por el sistema bajo prueba (SUT), que generalmente corresponde a un requisito . Si bien una unidad puede corresponder a una sola función o módulo (en programación procedimental ) o a un solo método o clase (en programación orientada a objetos ), las funciones/métodos y los módulos/clases no necesariamente corresponden a unidades. Desde la perspectiva de los requisitos del sistema, solo el perímetro del sistema es relevante; por lo tanto, solo los puntos de entrada a los comportamientos del sistema visibles externamente definen unidades. [ 11 ]

Ejecución

Las pruebas unitarias pueden realizarse manualmente o mediante la ejecución automatizada de pruebas . Las pruebas automatizadas ofrecen ventajas como: la posibilidad de ejecutar pruebas con frecuencia, la ausencia de costes de personal y la obtención de pruebas consistentes y repetibles.

Las pruebas suelen ser realizadas por el programador que escribe y modifica el código que se está probando. Las pruebas unitarias pueden considerarse parte del proceso de escritura de código.

Criterios de evaluación

Durante el desarrollo, un programador puede codificar criterios o resultados que se sabe que son buenos en la prueba para verificar la corrección de la unidad.

Durante la ejecución de las pruebas, los frameworks registran las pruebas que no cumplen con algún criterio y las presentan en un resumen.

Para ello, el enfoque más utilizado es prueba - función - valor esperado.

Caso de prueba

En ingeniería de software , un caso de prueba es una especificación de las entradas, las condiciones de ejecución, el procedimiento de prueba y los resultados esperados que definen una única prueba que se ejecutará para lograr un objetivo particular de prueba de software , como probar una ruta de programa específica o verificar el cumplimiento de un requisito específico. [ 12 ] Los casos de prueba sustentan las pruebas metódicas en lugar de las aleatorias. Se puede crear un conjunto de casos de prueba para producir la cobertura deseada del software que se está probando. Los casos de prueba definidos formalmente permiten ejecutar las mismas pruebas repetidamente en versiones sucesivas del software, lo que permite realizar pruebas de regresión efectivas y consistentes . [ 13 ]

Doble de prueba

Un simulador de pruebas es un software utilizado en la automatización de pruebas de software que satisface una dependencia , de modo que la prueba no dependa del código de producción. Un simulador de pruebas proporciona funcionalidad a través de una interfaz que el software bajo prueba no puede distinguir del código de producción.

Prueba parametrizada

Una prueba parametrizada es aquella que acepta un conjunto de valores que permiten ejecutarla con múltiples valores de entrada diferentes. Un marco de pruebas compatible con pruebas parametrizadas ofrece una forma de codificar conjuntos de parámetros y ejecutar la prueba con cada conjunto.

El uso de pruebas parametrizadas puede reducir la duplicación del código de prueba.

Las pruebas parametrizadas son compatibles con TestNG , JUnit , [ 14 ] XUnit y NUnit , así como con varios marcos de prueba de JavaScript.

Los parámetros para las pruebas unitarias pueden codificarse manualmente o, en algunos casos, generarse automáticamente mediante el marco de pruebas. En los últimos años se ha añadido soporte para escribir pruebas (unitarias) más potentes, aprovechando el concepto de teorías, casos de prueba que ejecutan los mismos pasos, pero utilizando datos de prueba generados en tiempo de ejecución, a diferencia de las pruebas parametrizadas regulares que utilizan los mismos pasos de ejecución con conjuntos de entrada predefinidos. [ 15 ]

Visibilidad del código

El código de prueba necesita acceso al código que está probando, pero las pruebas no deben comprometer los objetivos de diseño habituales, como la ocultación de información , la encapsulación y la separación de responsabilidades . Para permitir el acceso al código no expuesto en la API externa, las pruebas unitarias pueden ubicarse en el mismo proyecto o módulo que el código que se está probando.

En el diseño orientado a objetos, esto aún podría no proporcionar acceso a datos y métodos privados. Por lo tanto, podría ser necesario trabajo adicional para las pruebas unitarias. En Java y otros lenguajes, un desarrollador puede usar reflexión para acceder a campos y métodos privados. [ 16 ] Alternativamente, se puede usar una clase interna para alojar las pruebas unitarias, de modo que tengan visibilidad de los miembros y atributos de la clase contenedora. En .NET Framework y algunos otros lenguajes de programación, se pueden usar clases parciales para exponer métodos y datos privados a los que las pruebas puedan acceder.

Es importante que el código destinado exclusivamente a pruebas no permanezca en el código de producción. En C y otros lenguajes, se pueden colocar directivas del compilador#if DEBUG ... #endif alrededor de dichas clases adicionales y, de hecho, de todo el código relacionado con las pruebas para evitar que se compilen en el código publicado. Esto significa que el código publicado no es exactamente igual al que se probó unitariamente. La ejecución regular de menos pruebas de integración, pero más completas y de extremo a extremo, en la compilación de lanzamiento final puede garantizar (entre otras cosas) que no exista código de producción que dependa sutilmente de aspectos del entorno de pruebas .

Existe cierto debate entre los desarrolladores sobre si es conveniente probar métodos y datos privados. Algunos argumentan que los miembros privados son un mero detalle de implementación que puede cambiar y que debería permitirse que lo haga sin afectar la cantidad de pruebas. Por lo tanto, debería ser suficiente probar cualquier clase a través de su interfaz pública o a través de la interfaz de su subclase, que algunos lenguajes denominan interfaz "protegida". [ 17 ] Otros afirman que aspectos cruciales de la funcionalidad pueden implementarse en métodos privados y que probarlos directamente ofrece la ventaja de pruebas unitarias más pequeñas y directas. [ 18 ] [ 19 ]

desarrollo guiado por pruebas

En el desarrollo guiado por pruebas (TDD), las pruebas unitarias se escriben antes de escribir el código de producción correspondiente. Se comienza con una prueba que falla, luego se agrega el código de producción necesario para que la prueba pase, se refactoriza el código según sea necesario y se repite el proceso agregando otra prueba que falla.

Valor

Las pruebas unitarias tienen como objetivo garantizar que las unidades cumplan con su diseño y se comporten según lo previsto. [ 20 ]

Al escribir primero las pruebas para las unidades más pequeñas que se pueden probar, y luego los comportamientos compuestos entre ellas, se pueden construir pruebas exhaustivas para aplicaciones complejas. [ 20 ]

Uno de los objetivos de las pruebas unitarias es aislar cada parte del programa y demostrar que las partes individuales son correctas. [ 1 ] Una prueba unitaria proporciona un contrato escrito y estricto que el fragmento de código debe cumplir.

Detección temprana de problemas en el ciclo de desarrollo

Las pruebas unitarias detectan problemas en las primeras etapas del ciclo de desarrollo . Esto incluye tanto errores en la implementación del programador como fallos o partes faltantes en la especificación de la unidad. El proceso de escribir un conjunto exhaustivo de pruebas obliga al autor a analizar las entradas, las salidas y las condiciones de error, y así definir con mayor precisión el comportamiento deseado de la unidad. [ 21 ]

Costo reducido

El costo de encontrar un error antes de que comience la codificación o cuando se escribe el código por primera vez es considerablemente menor que el costo de detectarlo, identificarlo y corregirlo posteriormente. Los errores en el código publicado también pueden causar problemas costosos a los usuarios finales del software. [ 22 ] [ 23 ] [ 24 ] El código puede ser imposible o difícil de probar unitariamente si está mal escrito; por lo tanto, las pruebas unitarias pueden obligar a los desarrolladores a estructurar mejor las funciones y los objetos.

Lanzamientos más frecuentes

Las pruebas unitarias permiten lanzamientos más frecuentes en el desarrollo de software. Al probar componentes individuales de forma aislada, los desarrolladores pueden identificar y solucionar problemas rápidamente, lo que conduce a ciclos de iteración y lanzamiento más rápidos. [ 25 ]

Permite la refactorización del código.

Las pruebas unitarias permiten al programador refactorizar el código o actualizar las bibliotecas del sistema posteriormente, y asegurarse de que el módulo siga funcionando correctamente (por ejemplo, en las pruebas de regresión ). El procedimiento consiste en escribir casos de prueba para todas las funciones y métodos, de modo que, cuando un cambio provoque un fallo, este pueda identificarse rápidamente.

Detecta cambios que pueden incumplir un contrato de diseño.

Las pruebas unitarias detectan cambios que pueden incumplir un contrato de diseño .

Reducir la incertidumbre

Las pruebas unitarias pueden reducir la incertidumbre en las propias unidades y pueden utilizarse en un enfoque de pruebas ascendente . Al probar primero las partes de un programa y luego el conjunto de sus partes, las pruebas de integración resultan mucho más sencillas.

Documentación del comportamiento del sistema

Algunos programadores sostienen que las pruebas unitarias proporcionan una forma de documentación del código. Los desarrolladores que deseen conocer la funcionalidad de una unidad y cómo usarla pueden revisar las pruebas unitarias para comprenderla. [ 26 ]

Los casos de prueba pueden reflejar características cruciales para el éxito de la unidad. Estas características pueden indicar el uso adecuado o inadecuado de la unidad, así como comportamientos negativos que esta debe detectar. Un caso de prueba documenta estas características críticas, aunque muchos entornos de desarrollo de software no se basan únicamente en el código para documentar el producto en desarrollo.

En algunos procesos, la escritura de pruebas y del código bajo prueba, junto con la refactorización asociada, puede sustituir al diseño formal. Cada prueba unitaria puede considerarse un elemento de diseño que especifica clases, métodos y comportamiento observable. [ 27 ]

Limitaciones y desventajas

Las pruebas no detectarán todos los errores del programa, ya que no pueden evaluar todas las rutas de ejecución, salvo en los programas más triviales. Este problema es un superconjunto del problema de la parada , que es indecidible . Lo mismo ocurre con las pruebas unitarias. Además, por definición, las pruebas unitarias solo prueban la funcionalidad de las unidades en sí. Por lo tanto, no detectarán errores de integración ni errores más generales a nivel del sistema (como funciones que se ejecutan en varias unidades o áreas de prueba no funcionales, como el rendimiento ). Las pruebas unitarias deben realizarse junto con otras actividades de prueba de software , ya que solo pueden mostrar la presencia o ausencia de errores específicos; no pueden probar la ausencia total de errores. Para garantizar un comportamiento correcto para cada ruta de ejecución y cada entrada posible, y asegurar la ausencia de errores, se requieren otras técnicas, concretamente la aplicación de métodos formales para demostrar que un componente de software no presenta un comportamiento inesperado.

Una jerarquía elaborada de pruebas unitarias no equivale a pruebas de integración. La integración con unidades periféricas debe incluirse en las pruebas de integración, pero no en las unitarias. Las pruebas de integración suelen depender en gran medida de la intervención humana manual ; las pruebas de alto nivel o de alcance global pueden ser difíciles de automatizar, por lo que las pruebas manuales a menudo parecen más rápidas y económicas.

Las pruebas de software son un problema combinatorio. Por ejemplo, cada instrucción de decisión booleana requiere al menos dos pruebas: una con resultado "verdadero" y otra con resultado "falso". En consecuencia, por cada línea de código escrita, los programadores suelen necesitar de 3 a 5 líneas de código de prueba. Esto, obviamente, consume tiempo y su inversión puede no ser rentable. Existen problemas que no se pueden probar fácilmente, como por ejemplo, aquellos que no son deterministas o que involucran múltiples hilos . Además, el código para una prueba unitaria tiene la misma probabilidad de contener errores que el código que se está probando. Fred Brooks, en su libro "El hombre-mes mítico", cita: "Nunca te hagas a la mar con dos cronómetros; lleva uno o tres". [ 28 ] (Si dos cronómetros se contradicen, no se puede saber cuál es el correcto).

Dificultad para diseñar pruebas realistas y útiles.

Otro desafío relacionado con la escritura de pruebas unitarias es la dificultad de configurar pruebas realistas y útiles. Es necesario crear condiciones iniciales relevantes para que la parte de la aplicación que se está probando se comporte como parte del sistema completo. Si estas condiciones iniciales no se establecen correctamente, la prueba no ejercitará el código en un contexto realista, lo que disminuye el valor y la precisión de los resultados de las pruebas unitarias. [ 29 ]

Requiere disciplina durante todo el proceso de desarrollo.

Para obtener los beneficios previstos de las pruebas unitarias, se necesita una disciplina rigurosa a lo largo de todo el proceso de desarrollo de software.

Requiere control de versiones

Es fundamental mantener registros detallados no solo de las pruebas realizadas, sino también de todos los cambios introducidos en el código fuente de esta o cualquier otra unidad del software. El uso de un sistema de control de versiones es esencial. Si una versión posterior de la unidad falla una prueba que antes sí superaba, el software de control de versiones puede proporcionar una lista de los cambios en el código fuente (si los hubiera) que se hayan aplicado a la unidad desde entonces.

Requiere revisiones periódicas

También es fundamental implementar un proceso sostenible para garantizar que los fallos en los casos de prueba se revisen periódicamente y se aborden de inmediato. [ 30 ] Si no se implementa dicho proceso y no se integra en el flujo de trabajo del equipo, la aplicación evolucionará desincronizada con el conjunto de pruebas unitarias, lo que aumentará los falsos positivos y reducirá la eficacia del conjunto de pruebas.

Limitaciones del software para sistemas embebidos

Las pruebas unitarias de software de sistemas embebidos presentan desafíos porque el software se desarrolla en una plataforma diferente a aquella en la que finalmente se ejecutará, lo que dificulta ejecutar un programa de prueba en el entorno de implementación real, como es posible con los programas de escritorio. [ 31 ]

Limitaciones para probar la integración con sistemas externos

Las pruebas unitarias suelen ser más sencillas cuando un método tiene parámetros de entrada y alguna salida. No es tan fácil crear pruebas unitarias cuando una función principal del método es interactuar con algo externo a la aplicación. Por ejemplo, un método que trabajará con una base de datos podría requerir la creación de una simulación de las interacciones con la base de datos, que probablemente no será tan completa como las interacciones reales con la base de datos. [ 32 ]

Ejemplos

JUnit

A continuación se muestra un ejemplo de un conjunto de pruebas JUnit . Se centra en la Adderclase.

clase Adder { public int add ( int a , int b ) { return a + b ; } }

El conjunto de pruebas utiliza sentencias assert para verificar el resultado esperado de varios valores de entrada al summétodo.

import static org.junit.Assert.assertEquals ; import org.junit.Test ; public class AdderUnitTest { @Test public void sumReturnsZeroForZeroInput ( ) { Adder adder = new Adder (); assertEquals ( 0 , adder.add ( 0 , 0 ) ); }@Test public void sumReturnsSumOfTwoPositiveNumbers () { Adder adder = new Adder (); assertEquals ( 3 , adder . add ( 1 , 2 )); }@Test public void sumReturnsSumOfTwoNegativeNumbers () { Adder adder = new Adder (); assertEquals ( - 3 , adder . add ( - 1 , - 2 )); }@Test public void sumReturnsSumOfLargeNumbers () { Adder adder = new Adder (); assertEquals ( 2222 , adder . add ( 1234 , 988 )); } }

Como especificaciones ejecutables

El uso de pruebas unitarias como especificación de diseño presenta una ventaja significativa sobre otros métodos: el documento de diseño (las propias pruebas unitarias) puede utilizarse para verificar la implementación. Las pruebas nunca se superarán a menos que el desarrollador implemente una solución conforme al diseño.

Las pruebas unitarias carecen de algunas de las ventajas de una especificación diagramática, como un diagrama UML , pero pueden generarse a partir de la prueba unitaria mediante herramientas automatizadas. La mayoría de los lenguajes modernos cuentan con herramientas gratuitas (generalmente disponibles como extensiones para IDE ). Estas herramientas gratuitas, como las basadas en el framework xUnit , delegan a otro sistema la representación gráfica de una vista para su comprensión humana. [ 33 ]

Aplicaciones

Programación extrema

Las pruebas unitarias son la piedra angular de la programación extrema , que se basa en un marco de pruebas unitarias automatizadas . Este marco de pruebas unitarias automatizadas puede ser de terceros, como xUnit , o creado dentro del propio grupo de desarrollo.

La programación extrema utiliza la creación de pruebas unitarias para el desarrollo guiado por pruebas . El desarrollador escribe una prueba unitaria que expone un requisito de software o un defecto. Esta prueba fallará porque el requisito aún no se ha implementado o porque expone intencionadamente un defecto en el código existente. A continuación, el desarrollador escribe el código más sencillo para que la prueba, junto con las demás, pase.

La mayor parte del código de un sistema se somete a pruebas unitarias, pero no necesariamente todas las rutas de ejecución. La programación extrema exige una estrategia de "probar todo lo que pueda fallar", en contraposición al método tradicional de "probar cada ruta de ejecución". Esto lleva a los desarrolladores a crear menos pruebas que con los métodos clásicos, pero esto no es realmente un problema, sino más bien una constatación de un hecho, ya que los métodos clásicos rara vez se han seguido con la suficiente meticulosidad como para probar exhaustivamente todas las rutas de ejecución. [ 34 ] La programación extrema simplemente reconoce que las pruebas rara vez son exhaustivas (porque suelen ser demasiado costosas y requieren demasiado tiempo para ser económicamente viables) y proporciona orientación sobre cómo enfocar eficazmente los recursos limitados.

Fundamentalmente, el código de prueba se considera un artefacto de proyecto de primera clase, ya que se mantiene con la misma calidad que el código de implementación, eliminando toda duplicación. Los desarrolladores publican el código de prueba unitaria en el repositorio de código junto con el código que prueba. Las exhaustivas pruebas unitarias de la programación extrema permiten los beneficios mencionados anteriormente, como un desarrollo y refactorización de código más sencillos y seguros , una integración de código simplificada, documentación precisa y diseños más modulares. Estas pruebas unitarias también se ejecutan constantemente como una forma de prueba de regresión .

Las pruebas unitarias también son fundamentales para el concepto de Diseño Emergente , que desarrolla el diseño de software de forma iterativa a través de ciclos cortos de desarrollo guiado por pruebas , que consisten en escribir una prueba unitaria, hacer que pase y refactorizar; las pruebas unitarias proporcionan la red de seguridad contra la regresión que hace que la refactorización continua sea segura. [ 35 ]

Marcos de pruebas automatizadas

Un marco de pruebas automatizadas proporciona funcionalidades para automatizar la ejecución de pruebas y puede acelerar la escritura y ejecución de las mismas. Se han desarrollado marcos para una amplia variedad de lenguajes de programación .

Por lo general, los frameworks son de terceros y no se distribuyen con un compilador o un entorno de desarrollo integrado (IDE).

Se pueden escribir pruebas sin usar un framework para probar el código mediante aserciones , manejo de excepciones y otros mecanismos de control de flujo para verificar el comportamiento e informar sobre fallos. Algunos señalan que probar sin un framework es valioso, ya que existe una barrera de entrada para la adopción de uno, y que tener algunas pruebas es mejor que ninguna; sin embargo, una vez que se implementa un framework, agregar pruebas puede ser más fácil. [ 36 ]

En algunos frameworks, faltan funciones de prueba avanzadas y deben programarse manualmente.

Compatibilidad con pruebas unitarias a nivel de lenguaje

Algunos lenguajes de programación admiten directamente las pruebas unitarias. Su gramática permite la declaración directa de pruebas unitarias sin importar ninguna biblioteca (ya sea de terceros o estándar). Además, las condiciones booleanas de las pruebas unitarias se pueden expresar con la misma sintaxis que las expresiones booleanas utilizadas en código que no es de pruebas unitarias, como las que se usan para las sentencias ifAND while.

Los lenguajes con soporte integrado para pruebas unitarias incluyen:

Los lenguajes que admiten un marco de pruebas unitarias estándar incluyen:

Algunos lenguajes no tienen soporte integrado para pruebas unitarias, pero cuentan con bibliotecas o marcos de trabajo establecidos para este fin. Estos lenguajes incluyen:

Véase también

Referencias

  1. 1 2 Kolawa, Adam; Huizinga, Dorota (2007). Prevención automatizada de defectos: mejores prácticas en la gestión de software . Wiley-IEEE Computer Society Press. pág.  75. ISBN 978-0-470-04212-0.
  2. Amazon Web Services (AWS). (s.f.). ¿Qué son las pruebas unitarias? . Recuperado el 2 de mayo de 2025, de( https://aws.amazon.com/what-is/unit-testing/ )
  3. Benington, Herbert D. (1956). «Producción de grandes programas informáticos». Actas del Simposio sobre Métodos Avanzados de Programación para Computadoras Digitales, Washington, DC, 28-29 de junio de 1956. Oficina de Investigación Naval, Departamento de la Marina: 15-28 .
  4. 1 2 Benington, HD (1 de marzo de 1987). «Producción de grandes programas informáticos (reimpresión del artículo de 1956 con un prólogo actualizado)» . Actas de la 9.ª Conferencia Internacional sobre Ingeniería de Software . ICSE '87. Washington, DC, EE. UU.: IEEE Computer Society Press: 299–310 . ISBN 978-0-89791-216-7.
  5. Donegan, James J.; Packard, Calvin; Pashby, Paul (1 de enero de 1964). «Experiencias con el sistema informático Goddard durante misiones espaciales tripuladas» . Actas de la 19.ª conferencia nacional de la ACM de 1964. ACM '64. Nueva York, NY, EE . UU.: Association for Computing Machinery. págs. 12.101-12.108 . doi : 10.1145/800257.808889 . ISBN  978-1-4503-7918-2.{{cite book}}: Incompatibilidad de ISBN/Fecha ( ayuda )
  6. Zimmerman, Norman A. (26 de agosto de 1969). «La integración de sistemas como función de programación» . Actas de la 24.ª conferencia nacional de 1969. ACM '69. Nueva York, NY, EE. UU.: Association for Computing Machinery. págs. 459–467 . doi : 10.1145/800195.805951 . ISBN  978-1-4503-7493-4.
  7. MIL-STD-483 Norma militar: prácticas de gestión de configuración para sistemas, equipos, municiones y programas informáticos . Estados Unidos, Departamento de Defensa. 31 de diciembre de 1970. págs. Sección 3.4.7.2. El contratista deberá entonces codificar y probar las unidades de software, e introducir el código fuente y el código objeto, y los listados asociados de cada unidad probada con éxito en la configuración de desarrollo. 
  8. Tighe, Michael F. (1 de enero de 1978). "El valor de una metodología adecuada de garantía de calidad de software" . ACM SIGMETRICS Performance Evaluation Review . 7 ( 3–4 ): 165–172 . doi : 10.1145/1007775.811118 . ISSN 0163-5999 . 
  9. Gulati, Shekhar (2017). Java Unit Testing with JUnit 5 : Test Driven Development with JUnit 5 . Rahul Sharma. Berkeley, CA: Apress. p. 8. ISBN   978-1-4842-3015-2OCLC 1012347252 
  10. Winters, Titus (2020). Ingeniería de software en Google : lecciones aprendidas de la programación a lo largo del tiempo . Tom Manshreck, Hyrum Wright (1.ª ed.). Sebastopol, CA: O'Reilly. ISBN   978-1-4920-8274-3OCLC 1144086840 .​ 
  11. Beck, Kent (2002). Desarrollo guiado por pruebas mediante ejemplos . Addison-Wesley. ISBN 978-0321146533.
  12. Ingeniería de sistemas y software - Vocabulario . ISO/IEC/IEEE 24765:2010(E). 1 de diciembre de 2010. págs. 1–418 . doi : 10.1109/IEEESTD.2010.5733835 . ISBN  978-0-7381-6205-8.
  13. Kaner, Cem (mayo de 2003). "¿Qué es un buen caso de prueba?" (PDF) . STAR East : 2.
  14. Gulati y Sharma 2017 , págs. 133–137, Capítulo §7 Modelo de extensión JUnit 5: prueba parametrizada.
  15. Kampmann, Alexander; Zeller, Andreas (mayo de 2019). «Carving Parameterized Unit Tests». 2019 IEEE/ACM 41st International Conference on Software Engineering: Companion Proceedings (ICSE-Companion) . pp. 248–249 . doi : 10.1109/icse-companion.2019.00098 . ISBN  978-1-7281-1764-5.
  16. Burton, Ross (12 de noviembre de 2003). "Subvirtiendo la protección de acceso de Java para pruebas unitarias" . O'Reilly Media, Inc. Recuperado el 12 de agosto de 2009 .
  17. van Rossum, Guido; Warsaw, Barry (5 de julio de 2001). "PEP 8 -- Guía de estilo para código Python" . Python Software Foundation . Recuperado el 6 de mayo de 2012 .
  18. Newkirk, James (7 de junio de 2004). "Prueba de métodos privados/variables miembro: ¿Deberías hacerlo o no?" . Microsoft Corporation . Recuperado el 12 de agosto de 2009 .
  19. Stall, Tim (1 de marzo de 2005). "Cómo probar métodos privados y protegidos en .NET" . CodeProject. Archivado del original el 3 de septiembre de 2009. Consultado el 12 de agosto de 2009 .
  20. 1 2 Hamill, Paul (2004). Marcos de pruebas unitarias: Herramientas para el desarrollo de software de alta calidad . O'Reilly Media, Inc. ISBN 9780596552817.
  21. Gren, Lucas; Antinyan, Vard (agosto de 2017). Sobre la relación entre las pruebas unitarias y la calidad del código . 43.ª Conferencia Euromicro sobre Ingeniería de Software y Aplicaciones Avanzadas (SEAA). pp. 52–56 . doi : 10.1109/seaa.2017.36 . Recuperado el 16 de mayo de 2026 . 
  22. Boehm, Barry W. ; Papaccio, Philip N. (octubre de 1988). "Understanding and Controlling Software Costs" (PDF) . IEEE Transactions on Software Engineering . 14 (10): 1462– 1477. Bibcode : 1988ITSEn..14.1462B . doi : 10.1109/32.6191 . Archivado del original (PDF) el 9 de octubre de 2016 . Recuperado el 13 de mayo de 2016 .
  23. "Prueba pronto y con frecuencia" . Microsoft.
  24. "Demuestra que funciona: Uso del marco de pruebas unitarias para pruebas y validación de software" . National Instruments . 21 de agosto de 2017.
  25. Erik (10 de marzo de 2023). "Todavía no sabes cómo hacer pruebas unitarias (y tu secreto está a salvo conmigo)" . Stackify . Consultado el 10 de marzo de 2023 .
  26. Stocker, Karsten; Washizaki, Hironori; Fukazawa, Yoshiaki (marzo de 2017). «Cerrando la brecha entre el código de prueba unitaria y la documentación». 2017 IEEE International Conference on Software Testing, Verification and Validation Workshops (ICSTW) . págs. 304–308 . doi : 10.1109/icstw.2017.56 . ISBN  978-1-5090-6676-6.
  27. Nassif, M.; Hernandez, Alexa; Sridharan, Ashvitha; Robillard, M. (2022). "Generación de pruebas unitarias para documentación". IEEE Transactions on Software Engineering . 48 (9): 3268– 3279. arXiv : 2005.08750 . Bibcode : 2022ITSEn..48.3268N . doi : 10.1109/TSE.2021.3087087 .
  28. Brooks, Frederick J. (1995) [1975]. El hombre-mes mítico . Addison-Wesley. pág . 64. ISBN  978-0-201-83595-3.
  29. Tiwari, Deepika; Monperrus, Martin; Baudry, Benoit (noviembre de 2024). "Imitando el comportamiento de producción con simulaciones generadas". IEEE Transactions on Software Engineering . 50 (11): 2921– 2946. Bibcode : 2024ITSEn..50.2921T . doi : 10.1109/tse.2024.3458448 . ISSN 2326-3881 . 
  30. daVeiga, Nada (6 de febrero de 2008). "Cambia el código sin miedo: utiliza una red de seguridad de regresión" . Recuperado el 8 de febrero de 2008 .
  31. Kucharski, Marek (23 de noviembre de 2011). "Cómo hacer que las pruebas unitarias sean prácticas para el desarrollo de sistemas embebidos" . Recuperado el 20 de julio de 2020 .
  32. "Pruebas unitarias y bases de datos" . Consultado el 29 de enero de 2024 .
  33. GeeksforGeeks. (2024). Pruebas unitarias . Recuperado el 2 de mayo de 2025, de( https://www.geeksforgeeks.org/unit-testing-software-testing/ )
  34. Beck, Kent (octubre de 1999). "Extreme Programming Explained: Embrace Change" . Computer . 32 (10): 70–76 . doi : 10.1109/52.844236 (inactivo el 15 de mayo de 2026) . Recuperado el 7 de mayo de 2026 .{{cite journal}}: CS1 maint: DOI inactivo desde mayo de 2026 ( enlace )
  35. Fucci, Davide; Erdogmus, Hakan; Turhan, Burak; Oivo, Markku; Juristo, Natalia (2017). "Una disección del proceso de desarrollo guiado por pruebas: ¿Realmente importa probar primero o probar al final?" . IEEE Transactions on Software Engineering . 43 (7): 597– 614. doi : 10.1109/tse.2016.2616877 . ISSN 1939-3520 . Recuperado el 25 de mayo de 2026 . 
  36. Bullseye Testing Technology (2006–2008). "Objetivos de cobertura intermedios" . Consultado el 24 de marzo de 2009 .
  37. "Pruebas unitarias - Lenguaje de programación D" . Lenguaje de programación D. Fundación del lenguaje D. Consultado el 5 de agosto de 2017 .
  38. Steve Klabnik y Carol Nichols, con contribuciones de la comunidad Rust (2015–2023). "Cómo escribir pruebas" . Consultado el 21 de agosto de 2023 .
  39. "Crystal Spec" . crystal-lang.org . Consultado el 18 de septiembre de 2017 .
  40. "pruebas - El lenguaje de programación Go" . golang.org . Consultado el 3 de diciembre de 2013 .
  41. "Pruebas unitarias · El lenguaje Julia" . docs.julialang.org . Consultado el 15 de junio de 2022 .
  42. Documentación de Python (2016). "unittest -- Marco de pruebas unitarias" . Consultado el 18 de abril de 2016 .
  43. Welsh, Noel; Culpepper, Ryan. "RackUnit: Pruebas de unidad" . PLT Design Inc. Recuperado el 26 de febrero de 2019 .
  44. Welsh, Noel; Culpepper, Ryan. "El paquete de pruebas unitarias RackUnit forma parte de la distribución principal de Racket" . PLT Design Inc. Recuperado el 26 de febrero de 2019 .
  45. «Minitest (Ruby 2.0)» . Ruby-Doc.org.
  46. Sierra, Stuart. "API para clojure.test - Clojure v1.6 (estable)" . Consultado el 11 de febrero de 2015 .
  47. "Pester Framework" . GitHub . Consultado el 28 de enero de 2016 .

Lecturas adicionales

  • Feathers, Michael C. (2005). Trabajar eficazmente con código heredado . Upper Saddle River, NJ: Prentice Hall Professional Technical Reference. ISBN 978-0131177055.
  • Gulati, Shekhar; Sharma, Rahul (2017). Pruebas unitarias de Java con JUnit 5. Apress .
  • Desarrollo guiado por pruebas (Wikipedia de Ward Cunningham)