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."