digitalmars.dip.ideas - Allow `-version=unittest` flag
- Ilya (21/21) Apr 08 Currently D compilers don't allow passing `-version=unittest`
- Steven Schveighoffer (14/17) Apr 10 What you want is to be able to select the code to include using a
- Ilya (7/24) Apr 12 Thanks, what works indeed, I think we even use this pattern in
- Steven Schveighoffer (10/15) Apr 13 The `version(unittest)` means "the compiler was invoked with the
Currently D compilers don't allow passing `-version=unittest` flag explicitly, requiring to pass `-unittest` instead. But `-unittest` has a additional meaning: it will compile UTs as well! So, if I have two modules `A.d` and `B.d`, both define some UTs, `B` imports `A` **and** `A` has some `version(unittest)` blocks in non-templated code, there is no way to build **just** UTs from `B`. I can build `B` using `dmd -c -unittest B.d`, but there is no way to build `A` correctly: - if I build it without `-unittest`, conditional compilation for `version(unittest)` blocks won't trigger; - and if I build it with `-unittest`, I get also UTs from `A`. It's a simplified example, instead of two modules in reality it's a dependency chain of groups of modules, where each group is compiled in one step, but we still want to get separate UTs for every group, instead of getting everything in the root group. I get it, in D world people are usually compiling everything in one shot, so that's not a problem. But unfortunately this approach doesn't scale very well. How bad it will be to stop failing on `-version=unittest`? Seems like compiling UTs dependencies is a valid use case for it.
Apr 08
On Tuesday, 8 April 2025 at 13:26:42 UTC, Ilya wrote:How bad it will be to stop failing on `-version=unittest`? Seems like compiling UTs dependencies is a valid use case for it.What you want is to be able to select the code to include using a version statement, and also select it when you compile with unittests: ```d version(testing) void utThing() { ... } version(unittest) version = testing; // also enable for unittests ``` Now, you can build with unittests or with `-version=testing`, and the function is included. -Steve
Apr 10
On Thursday, 10 April 2025 at 19:13:18 UTC, Steven Schveighoffer wrote:On Tuesday, 8 April 2025 at 13:26:42 UTC, Ilya wrote:Thanks, what works indeed, I think we even use this pattern in some of our code. But it also feels like a workaround. So, I think my question still stands, why `version(unittest)` has to be special? Why can't we simply allow users set it without `-unittest`?How bad it will be to stop failing on `-version=unittest`? Seems like compiling UTs dependencies is a valid use case for it.What you want is to be able to select the code to include using a version statement, and also select it when you compile with unittests: ```d version(testing) void utThing() { ... } version(unittest) version = testing; // also enable for unittests ``` Now, you can build with unittests or with `-version=testing`, and the function is included.
Apr 12
On Saturday, 12 April 2025 at 10:46:37 UTC, Ilya wrote:Thanks, what works indeed, I think we even use this pattern in some of our code. But it also feels like a workaround. So, I think my question still stands, why `version(unittest)` has to be special? Why can't we simply allow users set it without `-unittest`?The `version(unittest)` means "the compiler was invoked with the `-unittest` flag". It shouldn't mean anything else. If you want to include more code in a related feature (such as custom-defined test functions), use a different version, and apply a version statement like I mentioned. Allowing specifying predefined versions on the command line loses the authority of the version statement. Should I be able to switch to `BigEndian` mode whenever I want? -Steve
Apr 13
On Monday, 14 April 2025 at 03:31:15 UTC, Steven Schveighoffer wrote:The `version(unittest)` means "the compiler was invoked with the `-unittest` flag". It shouldn't mean anything else.Ok, that's a fair point. If someone _actually_ needs to know if the compiler was invoked with `-unittest`, than yes, we definitely shouldn't allow setting it explicitly. But how useful is that? I was assuming `version(unittest)` means "I'm building unit tests" and then it's seems natural to extend it to "I'm building unit tests or UTs' dependencies".If you want to include more code in a related feature (such as custom-defined test functions), use a different version, and apply a version statement like I mentioned.Yes, the trick with another version works. And in the long run we should get rid of `version(unittest)` altogether, I think.Allowing specifying predefined versions on the command line loses the authority of the version statement. Should I be able to switch to `BigEndian` mode whenever I want?Ok, I see your point, even though I don't think it's a fair analogy. I can try to re-state my point. I think the `-unittest` flag should actually be ternary, not binary: apart from no-UT and UT options, there should also be a dep-UT option, that allows building dependencies of UTs with `version(unittest)`, but without building the UTs of dependencies. Otherwise people have to use the "custom-UT version" trick to build UTs with separate compilation. So I suggested to allow explicit `-d-version=unittest` as an easy way to enable that third option. But anyway, if people have strong opinions here, I'm not going to insist.
Apr 14
On Monday, 14 April 2025 at 09:03:20 UTC, Ilya wrote:I can try to re-state my point. I think the `-unittest` flag should actually be ternary, not binary: apart from no-UT and UT options, there should also be a dep-UT option, that allows building dependencies of UTs with `version(unittest)`, but without building the UTs of dependencies. Otherwise people have to use the "custom-UT version" trick to build UTs with separate compilation.You haven't really stated what the problem with compiling those 'UT deps' with `-unittest` (instead of just your proposed `-version=unittest`) is: - Just that those unittests are run by default too? The test runner can be customized, to only run the unittests of a subset of the linked modules. The druntime/Phobos unittest runners do just that, optionally allowing to specify the modules to be tested as cmdline options: https://github.com/dlang/dmd/blob/master/druntime/src/test_runner.d - The compilation overhead for those unittest functions? I'd say it's better to recompile a dirty module *once* in `-unittest` mode and using it for its own unittest runner, as well as those other unittest runners which require the module to be compiled with `-version=unittest` - instead of having to compile twice, once with `-unittest` and once with `-version=unittest` alone.I get it, in D world people are usually compiling everything in one shot, so that's not a problem.No, dub defaults to compiling each (non-source) (sub-)package in one shot. So if you replace your term 'group of modules' by 'dub packages/libraries', then that's exactly what most D users are building. The dub package dependencies can be tightly coupled as well (e.g., subpackages depending on one another), so this need to compile deps with `-version=unittest` for a parent project's unittest runner doesn't seem very popular. Out of interest, what's behind those `version (unittest)` blocks? Extra checks, or test helpers that dependents need?
Apr 14