From a conversation with @pmoura elsewhere, it occurs to me that this is something that is widely-known, yet widely not followed.
Some examples. Assuming that foo/1 asserts something and bar/1 extracts it (like a CHR constraint or some configuration setting):
my_test :- TestValue = 100, foo(TestValue), bar(TestValue).
This seems pretty elegant on the face of it, but if bar/1 fails to bind something in its body, the test will still succeed, even though it’s likely it shouldn’t. This is, of course, the implicit version of this code:
my_test :- TestValue = 100, foo(TestValue), bar(TestValueOut), TestValue = TestValueOut.
When this is written thusly it’s a bit more obvious what the little hole can be because it’s more visible what happens if bar/1 fails to bind something. In most cases the correct way to code this test is:
my_test :- TestValue = 100, foo(TestValue), bar(TestValueOut), TestValue == TestValueOut.
It turns out that unification isn’t always the right test. Who’d’ve thunk it?
This may sound “obvious”, and it is. But in the context of the conversation it was pointed out how often people make this very mistake. (@pmoura had been talking about his discoveries as he coded his linter.) And indeed in the course of that conversation I’d awoken to the horrible knowledge that not only had I fallen for this mistake, I’d moved from code equivalent to the third test to something equivalent to the first test because it was so damned “elegant”.
Elegance is nice, but it can be our enemy. Double-check your tests.