On Thu, Mar 22, 2018 at 10:59:56AM +0000, Atila Neves via 
Digitalmars-d-announce wrote:
> Blog post:
> 
> https://atilanevesoncode.wordpress.com/
[...]

I realize this is your opinion, but I disagree with them because:

1) I've found that having unittests built into the language is a big
win, *especially* because I can write tests next to the code being
tested. This is a big win because needing to open up a new file and
finding the right place to write the test is so much slower, and
distracts my focus from the code being written, and also when browsing
the code it's so much easier to find related unittests nearby to see if
a particular case has been tested or not, as opposed to having to open
up another file and searching for tests that *might* be relevant.

Case in point: just this week, for a particular project of mine I needed
to write external tests because refactoring would be too hard. So I
cooked up a simple test driver that scans a set of directories to pick
up test inputs and expected outputs. It was great that in D, this could
be done in just a couple of days' worth of work.  However, I did find
that needing to open up another file to create a new test, a second file
to put the expected output, and a third file to look at the source code
being tested, was a big slowdown for me.  I have to stop to think about
which subdirectory under test/ I should put the relevant file(s), or if
there's already a test there I have to stop to think about which
filename I saved it under, etc..  It's just yet another mental hurdle to
jump over while my already-busy brain is thinking about the code itself.
In my case it's a necessary evil, but would I do it for a project that
could just use inline unittests?  Definitely not.  But of course, YMMV.

2) Compilation times: perhaps if your unittests are too heavy,
compilation times could become a problem, but IME, they haven't been.
Plus, my opinion is that when you're compiling the code, you *should* be
running unittests anyway (otherwise regressions inevitably slip in), so
you're going to have to pay for the time taken to compile them
regardless. In that sense, it's actually better to have them in the same
file so that the compiler doesn't have to open up another file and
allocate resources for handling another module.

3) version(unittest): it's true that this can be a problem.  I remember
that in Phobos we used to merge PRs containing code that compiles fine
with -unittest, but in real-world code doesn't compile because it has
stuff outside unittests that depend on imports/declarations inside
version(unittest).  This is actually one of the reasons I was (and still
am) a big supporter of local/scoped imports. It may be more convenient
to just put global imports at the top of the module, but it just creates
too many implicit dependencies from mostly-unrelated chunks of code,
that I'm inclined actually to call global imports an anti-pattern.  In
fact, I'd even go so far to say that version(unittest) in general is a
bad idea.  It is better to factor out stuff inside version(unittest) to
a different module dedicated to unittest-specific stuff, and have each
unittest that needs it import that module.  This way you avoid polluting
the non-unittest namespace with unittest-specific symbols.

As for the dub-specific problems introduced by version(unittest): IMO
that's a flaw in dub.  I should not need to contort my code just to
accomodate some flaw in dub.  Having said that, though, I do agree that
version(unittest) itself is a bad idea, so code written the way I
recommend would not have this problem even given dub's flaws.


T

-- 
Programming is not just an act of telling a computer what to do: it is also an 
act of telling other programmers what you wished the computer to do. Both are 
important, and the latter deserves care. -- Andrew Morton

Reply via email to