OK, i’m used to good old C assertions, when they fail they output the condition they failed on, and the line it was on. (implimented with the preprocessor).
Now I’m programming in F# (a .net language), got code full of assert. (trying to program defensivly). and my assets show a popup with the call stack. according to the documentation could also pass the assert a string to display when it fails. so i could make it pass a string copy of my condition. eg:
assert (x=true, "x=true")
but this violate the Duplication (avoiding) principal.
If I later decide to change what I want to assert. (maybe i realised i was asserting something to be false when i should have been asserting it to be true) then I have to change the code in two places, otherwise the message won’t match what I’m actually checking. and if i forget things could be really confusing.
How is this normally dealt with?
Echoing what Tomas said, you can use quotations to avoid duplication. But instead of
ToLinqExpression -> ToString, which apparently produces C# source code, you can use my library Unquote which produces F# source code strings. Combine this with an implementation suitable for production code (i.e. definingAssertinline with a non-DEBUGcompilation symbol branch emitting only the no-op()means uses ofAssertwill be completely removed in non-DEBUGbuilds with optimizations turned on):then the assertion expression
Assert <@ (22 + 2) / 2 = ("assert" |> String.length) @>produces the following popup dialog by default (I think you can configureSystem.Diagnostics.Debugbehavior):Where in comparison
q.ToLinqExpression().ToString()produces(((22 + 2) / 2) == op_PipeRight("assert", ToFSharpFunc(str => Length(str)))).In fact, Unquote was designed specifically for the purpose of producing helpful unit test assertion failure messages, and can easily be adapted to debug assertions producing step-by-step failure messages: