Pensé que agregaría cuatro casos más, donde Debug.Assert puede ser la opción correcta.
1) Algo que no he visto mencionado aquí es la cobertura conceptual adicional que los Activos pueden proporcionar durante las pruebas automatizadas . Como un simple ejemplo:
Cuando un autor que modifica un llamador de nivel superior cree que ha ampliado el alcance del código para manejar escenarios adicionales, idealmente (!) Escribirán pruebas unitarias para cubrir esta nueva condición. Entonces puede ser que el código totalmente integrado parece funcionar bien.
Sin embargo, en realidad se introdujo un defecto sutil, pero no se detectó en los resultados de la prueba. El destinatario de la llamada se ha convertido no determinista en este caso, y sólo ocurre para proporcionar el resultado esperado. O tal vez ha arrojado un error de redondeo que pasó desapercibido. O provocó un error que fue compensado igualmente en otros lugares. O no solo se le otorga el acceso solicitado, sino también privilegios adicionales que no se deben otorgar. Etc.
En este punto, las declaraciones Debug.Assert () contenidas en el destinatario junto con el nuevo caso (o caso límite) conducido por pruebas unitarias pueden proporcionar una notificación invaluable durante la prueba de que los supuestos del autor original han sido invalidados, y el código no debe ser lanzado sin revisión adicional. Las afirmaciones con pruebas unitarias son los socios perfectos.
2) Además, algunas pruebas son simples de escribir, pero de alto costo e innecesarias dados los supuestos iniciales . Por ejemplo:
Si solo se puede acceder a un objeto desde un determinado punto de entrada seguro, ¿se debe realizar una consulta adicional a una base de datos de derechos de red desde cada método de objeto para garantizar que la persona que llama tenga permisos? Seguramente no. Quizás la solución ideal incluye el almacenamiento en caché o alguna otra expansión de características, pero el diseño no lo requiere. Debug.Assert () mostrará inmediatamente cuando el objeto se haya adjuntado a un punto de entrada inseguro.
3) Luego, en algunos casos, su producto puede no tener una interacción de diagnóstico útil para todas o parte de sus operaciones cuando se implementa en modo de lanzamiento . Por ejemplo:
Supongamos que es un dispositivo incorporado en tiempo real. Lanzar excepciones y reiniciar cuando encuentra un paquete mal formado es contraproducente. En cambio, el dispositivo puede beneficiarse de la operación de mejor esfuerzo, incluso hasta el punto de generar ruido en su salida. Es posible que tampoco tenga una interfaz humana, un dispositivo de registro o incluso que un humano pueda acceder físicamente cuando se implementa en modo de liberación, y la mejor manera de obtener conocimiento de los errores es evaluando la misma salida. En este caso, las afirmaciones liberales y las pruebas exhaustivas previas al lanzamiento son más valiosas que las excepciones.
4) Por último, algunas pruebas son innecesarias solo porque la persona que llama se percibe como extremadamente confiable . En la mayoría de los casos, cuanto más reutilizable es el código, más esfuerzo se ha hecho para hacerlo confiable. Por lo tanto, es común a Exception para parámetros inesperados de las personas que llaman, pero Assert para resultados inesperados de personas que llaman. Por ejemplo:
Si una String.Find
operación principal indica que devolverá un -1
cuando no se encuentran los criterios de búsqueda, es posible que pueda realizar una operación de forma segura en lugar de tres. Sin embargo, si realmente regresó -2
, es posible que no tenga un curso de acción razonable. Sería inútil reemplazar el cálculo más simple con uno que pruebe un -1
valor por separado , y que no sea razonable en la mayoría de los entornos de lanzamiento para ensuciar su código con pruebas que garanticen que las bibliotecas principales funcionen como se espera. En este caso, las afirmaciones son ideales.