How can one reliably run unittests

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Aug 24 17:03:36 UTC 2021


On Tue, Aug 24, 2021 at 12:21:41PM +0000, deadalnix via Digitalmars-d wrote:
[...]
> Some of these component are libraries, some are executable. Adding a
> main for libraries is required, or it won't link, but adding one to
> executable is going to cause a link error. This in itself is a major
> main in the ass, because that means there is no one consistent way to
> unittest a module without knowing if that module has a main. In
> addition, everything needs to be built twice now, which is really
> undesirable.

There's the `-main` flag for adding an empty main() to the compiled
sources.  But yeah, if there's already a main() it will die with a
compile error.  The hack solution for this is to prepend this to your
main(), like this:

	version(unittest){} else
	void main() {
		...
	}


The point about building everything twice is legit, and is a pain point
I myself have come across.  In the old days, -unittest used to just run
unittests before invoking main(). Then somebody changed this so that
-unittest causes main() not to run.  So when coding/compiling/debugging,
I now need to build the program twice: once with -unittest, once
without.

Technically this isn't avoidable (no) thanks to `version(unittest)`: the
object files may have very different contents so compiling twice is
almost unavoidable. But in the normal, common case, there isn't *that*
much of a difference, and it would be nice to only have to compile once
(like in the old days).


> Maybe one could rdmd each modules to runt he tests? That seems like
> the best approach to me, considering one doesn't want to actually
> produce an artifact for the tests, simply run them. this also has the
> main/no main problem, but in addition, it often fails with
> incomprehensible linker errors. For some reason, rdmd is not able to
> include all dependencies consistently, but, even better, it doesn't
> take the same standard flags as other linkers do, so it is not
> possible to reuse existing build infrastructure to feed all the
> correct flags to rdmd.

Honestly, these days I find little need for rdmd. I can just run `dmd
-unittest -main -i -run main.d` and it will compile unittests, insert an
empty main(), and pull in all imports, run the resulting executable, and
clean up afterwards. Just a single command line takes care of it all.

Well, modulo the `version(unittest) else` hack for main().


> This may seems like it wouldn't be that big of a deal if you manage
> all your flags by yourself, but very quickly turns into a nightmare
> once you have to use 3rd party libraries that ship with their own set
> of flags.

Which means we need dub support for this. :-D


> At this point, I would just wish that one could rdmd --unittest
> modulename.d and just pass it a couple of -I, -L and -l flags and have
> all of it work. I have no idea how to achieve that.
[...]

As I already said:

	dmd -unittest -main -i -run main.d


T

-- 
Only boring people get bored. -- JM


More information about the Digitalmars-d mailing list