Bueno ... sí , en realidad, si se prueba cada ruta "a través" del programa. Pero eso significa que cada ruta posible a través del espacio completo de todos los estados posibles que puede tener el programa, incluidas todas las variables. Incluso para un programa compilado estáticamente muy simple, por ejemplo, un viejo generador de números Fortran, eso no es factible, aunque al menos puede ser imaginable: si solo tiene dos variables enteras, básicamente está tratando con todas las formas posibles de conectar puntos en una cuadrícula bidimensional; en realidad se parece mucho a un vendedor ambulante. Para n de tales variables, se trata de un espacio n -dimensional, por lo que para cualquier programa real, la tarea es completamente imposible de manejar.
Peor aún: para cosas serias, no solo tiene un número fijo de variables primitivas, sino que crea variables sobre la marcha en llamadas a funciones, o tiene variables de tamaño variable ... o algo así, como sea posible en un lenguaje completo de Turing. Eso hace que el espacio de estado sea de dimensión infinita, rompiendo todas las esperanzas de una cobertura total, incluso con equipos de prueba absurdamente poderosos.
Dicho eso ... en realidad las cosas no son tan sombrías. Que es posible proove programas enteros a ser correcta, pero usted tendrá que renunciar a algunas ideas.
Primero: es muy recomendable cambiar a un lenguaje declarativo. Los lenguajes imperativos, por alguna razón, siempre han sido de lejos los más populares, pero la forma en que combinan algoritmos con interacciones del mundo real hace que sea extremadamente difícil incluso decir lo que quiere decir con "correcto".
Mucho más fácil en lenguajes de programación puramente funcionales : tienen una clara distinción entre las propiedades realmente interesantes de las funciones matemáticas y las interacciones difusas del mundo real sobre las que realmente no se puede decir nada. Para las funciones, es muy fácil especificar el "comportamiento correcto": si para todas las entradas posibles (de los tipos de argumento) sale el resultado deseado correspondiente, entonces la función se comporta correctamente.
Ahora, dices que todavía es intratable ... después de todo, el espacio de todos los argumentos posibles es en general también de dimensión infinita. Es cierto, aunque para una sola función, ¡incluso las pruebas de cobertura ingenuas lo llevan más allá de lo que podría esperar en un programa imperativo! Sin embargo, hay una herramienta increíblemente poderosa que cambia el juego: cuantificación universal / polimorfismo paramétrico . Básicamente, esto le permite escribir funciones en tipos de datos muy generales, con la garantía de que si funciona para un ejemplo simple de los datos, funcionará para cualquier entrada posible.
Al menos teóricamente. No es fácil encontrar los tipos correctos que son realmente tan generales que puede probar esto completamente; por lo general, necesita un lenguaje de tipo dependiente , y estos tienden a ser bastante difíciles de usar. Pero escribir en un estilo funcional con polimorfismo paramétrico solo aumenta enormemente su "nivel de seguridad": no necesariamente encontrará todos los errores, ¡pero tendrá que ocultarlos bastante bien para que el compilador no los detecte!