Thread overview
Shared static this() not executed for unittest
Dec 15, 2018
Timoses
Dec 15, 2018
Neia Neutuladh
Dec 15, 2018
Jonathan M Davis
Dec 17, 2018
Jonathan M Davis
Dec 15, 2018
Timoses
December 15, 2018
Spec 27.5 states: "Unit tests, when enabled, are run after all static initialization is complete and before the main() function is called. " (https://dlang.org/spec/unittest.html)


main.d:
-------------------
import std.stdio;

shared static this()
{
    import vibe.core.log;
    setLogLevel(LogLevel.trace);

    logDebug("log: statc this");
    WRITELN("WRiteln: static this");
}

void main()
{
    writeln("Edit source/app.d to start your project.");
}

test.d:
-------------------
import std.stdio;

unittest
{
    import vibe.core.log;
    logDebug("log: unittest");
    writeln("writeln: unittest");
}


Running `dub test` will output:
Running ./unit-test-library
writeln: unittest
All unit tests have been run successfully.

Why is the `shared static this()` not executed?
December 15, 2018
On Sat, 15 Dec 2018 17:19:05 +0000, Timoses wrote:
> Running `dub test` will output:
> Running ./unit-test-library writeln: unittest All unit tests have been
> run successfully.
> 
> Why is the `shared static this()` not executed?

Run `dub clean; dub test -v` and you'll see that main.d isn't compiled into the test library.

dub test substitutes its own main() function over yours. In order to do this, it needs to not compile in your main() and to compile in its own. dmd doesn't have an option to replace main(), so dub drops that entire source file.
December 15, 2018
A look into `dub test --vverbose` showed that ./source/app.d is not even included in the compilcation step...
December 15, 2018
On Saturday, December 15, 2018 10:27:36 AM MST Neia Neutuladh via Digitalmars-d-learn wrote:
> On Sat, 15 Dec 2018 17:19:05 +0000, Timoses wrote:
> > Running `dub test` will output:
> > Running ./unit-test-library writeln: unittest All unit tests have been
> > run successfully.
> >
> > Why is the `shared static this()` not executed?
>
> Run `dub clean; dub test -v` and you'll see that main.d isn't compiled into the test library.
>
> dub test substitutes its own main() function over yours. In order to do
> this, it needs to not compile in your main() and to compile in its own.
> dmd doesn't have an option to replace main(), so dub drops that entire
> source file.

Yeah. I hate how dub does this. I've been bitten by it on multiple occasions, and it's really easy to miss that this is happening. It probably would have been better if it required you to deal with main when the target type is an executable, resulting in a linker error when you didn't provide one. Instead, a number of us do stuff like

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

thinking that it's working, but whatever tests in the module with main simply don't get run, because that module isn't compiled in. Maybe dub should check the module with main to see if it contains any unittest blocks and print out warning if it does, but even if it did, it actually wouldn't have caught this case, because it involves a static constructor, not a unittest block.

Anyway, the way that dub deals with this probably makes it so that the best thing to do in general is to make it so that the module with main is pretty much literally something like

int main(string[] args)
{
    import somemodulename;
    return realmain(args);
}

But of course, that just makes it so that you're less likely to accidentally do something like create a static this which won't be called with -unittest when you already know that that sort of thing is a problem with dub test. It doesn't help those folks who aren't aware of this behavior or who forget it.

- Jonathan M Davis



December 16, 2018
On 12/15/18 5:14 PM, Jonathan M Davis wrote:
> On Saturday, December 15, 2018 10:27:36 AM MST Neia Neutuladh via
> Digitalmars-d-learn wrote:
>> On Sat, 15 Dec 2018 17:19:05 +0000, Timoses wrote:
>>> Running `dub test` will output:
>>> Running ./unit-test-library writeln: unittest All unit tests have been
>>> run successfully.
>>>
>>> Why is the `shared static this()` not executed?
>>
>> Run `dub clean; dub test -v` and you'll see that main.d isn't compiled
>> into the test library.
>>
>> dub test substitutes its own main() function over yours. In order to do
>> this, it needs to not compile in your main() and to compile in its own.
>> dmd doesn't have an option to replace main(), so dub drops that entire
>> source file.
> 
> Yeah. I hate how dub does this. I've been bitten by it on multiple
> occasions, and it's really easy to miss that this is happening. It probably
> would have been better if it required you to deal with main when the target
> type is an executable, resulting in a linker error when you didn't provide
> one. Instead, a number of us do stuff like

This should be fixed, as DMD now supports just running the program with --DRT-testmode=test-only and it will only run unit tests.

-Steve
December 17, 2018
On Sunday, December 16, 2018 12:53:43 PM MST Steven Schveighoffer via Digitalmars-d-learn wrote:
> On 12/15/18 5:14 PM, Jonathan M Davis wrote:
> > On Saturday, December 15, 2018 10:27:36 AM MST Neia Neutuladh via
> >
> > Digitalmars-d-learn wrote:
> >> On Sat, 15 Dec 2018 17:19:05 +0000, Timoses wrote:
> >>> Running `dub test` will output:
> >>> Running ./unit-test-library writeln: unittest All unit tests have been
> >>> run successfully.
> >>>
> >>> Why is the `shared static this()` not executed?
> >>
> >> Run `dub clean; dub test -v` and you'll see that main.d isn't compiled into the test library.
> >>
> >> dub test substitutes its own main() function over yours. In order to do
> >> this, it needs to not compile in your main() and to compile in its own.
> >> dmd doesn't have an option to replace main(), so dub drops that entire
> >> source file.
> >
> > Yeah. I hate how dub does this. I've been bitten by it on multiple occasions, and it's really easy to miss that this is happening. It probably would have been better if it required you to deal with main when the target type is an executable, resulting in a linker error when you didn't provide one. Instead, a number of us do stuff like
>
> This should be fixed, as DMD now supports just running the program with --DRT-testmode=test-only and it will only run unit tests.

That would be fantastic.

- Jonathan M Davis