On 09/24/2016 03:34 AM, Jonathan M Davis via Digitalmars-d wrote:
On Friday, September 23, 2016 23:50:03 Nick Sabalausky via Digitalmars-d
wrote:
And then that leads too, to the question of whether such third-party
asserts are a good idea for the doc unittests I like so much... :/
I'd say not. If you're writing a library for general consumption, I don't
think that anyone else who is not actually helping to develop it should have
to know or care what unit testing facilities you're using. assert is
universal and clear, whereas other stuff is not universal and may or may not
be clear to those not familiar with it.
Yea, honestly, that's my thought as well. :( And it's a big part of why
I was (and still am) so disappointed that assertPred didn't become
official even if it is technically usable as third-party. We could've
already been using that for years by now, standard, if it weren't for
D's habit of letting perfect be the enemy of progress.
Also, my take on it is that ddoc-ed unittest blocks are really there to just
give examples for the documentation, not to test your code. You want the
examples tested so that you know that they work - which is why ddoc-ed
unittest blocks are such a great feature - but it's not their purpose to
test your library. It would be wholly unreasonable to have thorough tests in
the documentation, and what makes a good example doesn't necessarily make
for a very good test (or vice versa).
I think there's a balance (albeit a difficult one). I agree that being
pedantic with the examples can make them overly cluttered, so that
should be avoided. But all major side-cases should still be documented,
and examples help with that as they do with anything else.
For example, std.path.buildNormalizedPath: It should not only document
typical cases like `buildNormalizedPath("foo","bar")`, but it's very
important for its docs to also be clear about various other significant
cases:
- How does it handle empty strings as arguments?
- What does it return for buildNormalizedPath("foo",".."). It used to
return empty string which turned out very problematic. Now it returns
"." which is much better.
- What happens when I do buildNormalizedPath(relativePath,absolutePath)?
These are all very important cases that still need to be documented. And
examples work excellently as documentation here. (And IIRC,
buildNormalizedPath docs are doing a good job of this.)
So a good set of examples *do* still test a significant amount of a
function, even if it isn't exhaustive.
So because of that, and heck, even if your examples *are* overly sparse,
sometimes you will get a failure in one. Which, of course, is the whole
point of actually testing them. And when you do, it's a big help for the
diagnostic output to actually be, well, helpful:
The whole cycle of:
- Search the stack trace for the relevant file/line number.
- Find it:
assert(x.foo(blah...) == y);
- Insert scaffolding:
import std.stdio;
writeln("x.foo(blah...): ", x.foo(blah...));
writeln("y: ", y);
- Recompile/re-run tests (and maybe go back again and fix any stupid
typos in the scaffolding).
- Finally view key information that COULD'VE been shown right from the
start.
Gets very tiresome very quickly, even if it's only in the example tests.