C # - ¿Qué hace el método Assert ()? ¿Sigue siendo útil?

156

Estoy depurando con puntos de interrupción y me doy cuenta de la llamada de afirmación? Pensé que era solo para pruebas unitarias. ¿Qué hace más que el punto de interrupción? Como puedo romper el punto, ¿por qué debería usar Assert?

Pokus
fuente
9
Por cierto, si está interesado en afirmaciones, definitivamente debería profundizar en los contratos de código .
MasterMastic
Posible duplicado de stackoverflow.com/questions/129120/…
Michael Freidgeim

Respuestas:

200

En una compilación de depuración, Asserttoma una condición booleana como parámetro y muestra el diálogo de error si la condición es falsa. El programa continúa sin interrupción si la condición es verdadera.

Si compila en Release, todos se Debug.Assertomiten automáticamente.

Patrick Desjardins
fuente
12
¿Cómo puedo obtener el mismo comportamiento de Debug.Assert en modo Release?
Hamish Grubijan
15
Trace.Assert para el modo de lanzamiento aparentemente referencias: msdn.microsoft.com/en-us/library/… msdn.microsoft.com/en-us/library/e63efys0.aspx
Tim Abell
8
@HamishGrubijan ¿Y por qué querrías Debug.Asserten modo de lanzamiento?
Camilo Martin
25
En mi opinión, omitir afirmaciones del código de lanzamiento es como realizar simulacros de botes salvavidas mientras está atracado y luego dejar los botes salvavidas cuando navegas. :)
Chris
113
Las afirmaciones no son un bote salvavidas, son un sistema de detección de iceberg. Como el usuario no dirige el barco, una afirmación en el código de lanzamiento solo les dice que están condenados; No les permite evitar el iceberg.
Stefan
97

Desde el código completo

8 Programación defensiva

8.2 Afirmaciones

Una aserción es un código que se usa durante el desarrollo, generalmente una rutina o macro, que permite que un programa se verifique a sí mismo mientras se ejecuta. Cuando una afirmación es verdadera, eso significa que todo está funcionando como se esperaba. Cuando es falso, eso significa que ha detectado un error inesperado en el código. Por ejemplo, si el sistema supone que un archivo de información del cliente nunca tendrá más de 50,000 registros, el programa podría contener una afirmación de que el número de registros es menor o igual a 50,000. Mientras el número de registros sea menor o igual a 50,000, la afirmación será silenciosa. Sin embargo, si encuentra más de 50,000 registros, "afirmará" en voz alta que hay un error en el programa.

Las afirmaciones son especialmente útiles en programas grandes y complicados y en programas de alta confiabilidad. Permiten a los programadores eliminar más rápidamente las suposiciones de interfaz no coincidentes, los errores que se arrastran cuando se modifica el código, etc.

Una aserción generalmente toma dos argumentos: una expresión booleana que describe la suposición que se supone que es verdadera y un mensaje para mostrar si no lo es.

(...)

Normalmente, no desea que los usuarios vean mensajes de afirmación en el código de producción; Las afirmaciones son principalmente para uso durante el desarrollo y mantenimiento. Las afirmaciones normalmente se compilan en el código en el momento del desarrollo y se compilan fuera del código para la producción. Durante el desarrollo, las afirmaciones eliminan suposiciones contradictorias, condiciones inesperadas, valores incorrectos pasados ​​a las rutinas, etc. Durante la producción, se compilan del código para que las afirmaciones no degraden el rendimiento del sistema.

juan
fuente
2
El libro, Writing Solid Code, también tiene una gran discusión sobre el uso de la afirmación. ¡Son una gran herramienta de depuración!
zooropa
39

Debe usarlo en momentos en que no desee tener que romper cada pequeña línea de código para verificar las variables, pero sí desea obtener algún tipo de retroalimentación si ciertas situaciones están presentes, por ejemplo:

Debug.Assert(someObject != null, "someObject is null! this could totally be a bug!");
thelsdj
fuente
Si agrego una línea de código similar a la suya anterior, la ejecución de mi programa da el siguiente error: "error CS0103: el nombre 'Debug' no existe en el contexto actual". ¿Necesito algún tipo de declaración de uso para que funcione?
Josh Desmond
44
@JoshDesmondSystem.Diagnostics
Sinjai
16

Assert también le brinda otra oportunidad para reírse de las habilidades de diseño de la interfaz de usuario de Microsoft. Quiero decir: un diálogo con tres botones Abortar, Reintentar, Ignorar, y una explicación de cómo interpretarlos en la barra de título.

Joe
fuente
3
¡Abortar / Reintentar / Ignorar es clásico! ¿Fueron las afirmaciones las que solían hacer que Windows 3.1 mostrara esto todo el tiempo?
devlord
Básicamente es porque usa un cuadro de mensaje, que como usted dice data de Windows 3.1, y solo tiene etiquetas de botones predefinidas. ¡Entonces puedes entender por qué ocurrió el hack, pero no por qué todavía está allí en 2008!
Joe
44
@ Joe Esto es algo que solo deberían ver los desarrolladores, no los usuarios finales, por lo que actualizarlo es probablemente un elemento de prioridad extremadamente baja. Si le molesta, puede modificar las colecciones Debug.Listeners o Trace.Listeners para reemplazar el controlador predeterminado por uno que haga lo que desee.
Dan Is Fiddling By Firelight
55
¡Y ahora es 2019 y los mismos cuadros de diálogo / botones todavía están aquí!
Bouke
10

Assert le permite afirmar que una condición (post o pre) se aplica en su código. Es una forma de documentar sus intenciones y hacer que el depurador le informe con un diálogo si no se cumple su intención.

A diferencia de un punto de interrupción, Assert va con su código y puede usarse para agregar detalles adicionales sobre su intención.

Jeff Yates
fuente
10

Assert puede ayudarlo a proporcionar un comportamiento de mensajería separado entre las pruebas y el lanzamiento. Por ejemplo,

Debug.Assert(x > 2)

solo activará una interrupción si está ejecutando una compilación de "depuración", no una compilación de lanzamiento. Hay un ejemplo completo de este comportamiento aquí

Ryan
fuente
10

En primer lugar, el Assert()método está disponible para Tracey Debugclases.
Debug.Assert()se ejecuta solo en modo de depuración.
Trace.Assert()se está ejecutando en modo de depuración y liberación.

Aquí hay un ejemplo:

        int i = 1 + 3;
        // Debug.Assert method in Debug mode fails, since i == 4
        Debug.Assert(i == 3);
        Debug.WriteLine(i == 3, "i is equal to 3");

        // Trace.Assert method in Release mode is not failing.
        Trace.Assert(i == 4);
        Trace.WriteLine(i == 4, "i is equla to 4");

        Console.WriteLine("Press a key to continue...");
        Console.ReadLine();

Ejecute este código en modo de depuración y luego en modo de lanzamiento.

ingrese la descripción de la imagen aquí

Notará que durante el modo de depuración Debug.Assertfalla su declaración de código , aparece un cuadro de mensaje que muestra el seguimiento actual de la pila de la aplicación. Esto no está sucediendo en el modo Release ya que la Trace.Assert()condición es verdadera (i == 4).

WriteLine() El método simplemente le ofrece la opción de registrar la información en la salida de Visual Studio. ingrese la descripción de la imagen aquí

Serge Voloshenko
fuente
5

Las afirmaciones son muy importantes en Design by Contract (DbC) que, según tengo entendido, fue presentado / respaldado por Meyer, Bertand. 1997. Construcción de software orientado a objetos.

Una característica importante es que no deben producir efectos secundarios, por ejemplo, puede manejar una excepción o tomar un curso de acción diferente con una declaración if (programación defensiva).

Las afirmaciones se utilizan para verificar las condiciones previas / posteriores del contrato, la relación cliente / proveedor; el cliente debe asegurarse de que se cumplan las condiciones previas del proveedor, por ejemplo. envía £ 5 y el proveedor debe asegurarse de que se cumplan las condiciones posteriores, por ejemplo. entrega 12 rosas. (Solo una explicación simple del cliente / proveedor: puede aceptar menos y entregar más, pero sobre Afirmaciones). C # también presenta Trace.Assert (), que se puede usar para liberar código.

Para responder a la pregunta sí, siguen siendo útiles, pero pueden agregar complejidad + legibilidad al código y tiempo + difícil de mantener. ¿Deberíamos seguir usándolos? Sí, ¿los usaremos todos? Probablemente no, o no en la medida en que Meyer lo describe.

(¡Incluso el curso OU Java en el que aprendí esta técnica solo mostró ejemplos simples y el resto del código no hizo cumplir las reglas de afirmación de DbC en la mayoría del código, pero se asumió que se usaba para garantizar la corrección del programa!)

Knightlore
fuente
3

La forma en que pienso es Debug.Assert es una forma de establecer un contrato sobre cómo se debe llamar a un método, centrándose en detalles sobre los valores de un parámetro (en lugar de solo el tipo). Por ejemplo, si se supone que no debe enviar un valor nulo en el segundo parámetro, agregue la afirmación alrededor de ese parámetro para decirle al consumidor que no lo haga.

Impide que alguien use su código de una manera descabellada. Pero también permite que esa manera descabellada de pasar a la producción y no dar el mensaje desagradable a un cliente (suponiendo que construya una versión de lanzamiento).

Flory
fuente
66
Sin embargo, es importante señalar que los parámetros no válidos en los métodos públicos deberían arrojar excepciones de argumentos. Solo los métodos privados deben validar la entrada con aserciones. ¡Los valores que vienen del exterior siempre son sospechosos!
Jeffrey L Whitledge