On Fri, Dec 29, 2017 at 05:52:36PM -0700, Jonathan M Davis via Digitalmars-d 
wrote:
[...]
> Oh, certainly. But my point is that once it starts taking minutes to
> be able to build and run the unit tests for what you're currently
> doing, it becomes infeasible to edit-test-edit-etc. in any kind of
> reasonable cycle. It doesn't have to get anywhere near the 30 minute
> mark for it to be a serious problem. So, of course, 30+ minutes is an
> utter disaster if you're looking to test stuff as you go.
[...]

Yeah... recently I've been resorting to `dmd -unittest -main module.d`
on single modules for faster turnaround time, because in spite of D's
famed compilation speeds, some things still make it go far too slow,
e.g. if you use template-heavy / CTFE-heavy code, or there are just too
many files to compile.

This has also been encouraging me to write code in a far more modular
fashion than even traditional modularists would do, in the sense that
where possible, even dependent modules won't be imported, but instead
left to a template parameter, to be instantiated by the main program
with the dependent module. Contrived example:

-----
void printSomething(alias stdio = selfImport!"std.stdio", Args...)(string fmt, 
Args args)
{
        stdio.writefln(fmt, args);
}

unittest
{
        struct TestHarness {
                static void writefln() { /* fake implementation here */ }
        }
        printSomething!TestHarness("%s", "blah");
}
-----

The idea is that importing std.stdio won't even happen when compiling
with -unittest -main. This approach lets you completely detach a module
from its dependencies, so you never have to worry about what else it
depends on when compiling with -unittest -main, and also conveniently
allows you to substitute complicated types with cheaper substitutes that
suffice for testing, e.g., instead of writing to stdout or actually
causing side-effects visible outside the program, have a substitute
module (or just struct!) that redirects output or filesystem changes to
a log that's verified by the unittest to be the correct sequence of
operations. The substitute type doesn't even have to implement the
complete API of the module/object in question; just enough of it for the
unittest to do what it needs to do.

Being able to substitute a struct in place of a module inside a unittest
is one of the awesome things about D that make me love it so. :-D

And a side perk is that you'll get automatic attribute inference for all
such functions, if the original function would otherwise be just a
non-template function. (On that note, nowadays I'm tempted to just stick
empty compile-time parameters on every function I can; it enables
attribute inference and also reduces executable bloat if the function is
never actually called from anywhere. The only bad thing is the compiler
won't run semantic on potentially broken code... but then again, if you
never use it, it doesn't matter, and if it ought to matter, there should
be a unittest for it anyway.)


T

-- 
"You are a very disagreeable person." "NO."

Reply via email to