A customer was hoping for a simpler way to structure their unit tests: They had a Visual Studio solution with two projects, Contoso and ContosoUnitTest. Every time they add a new cpp file to Contoso, they have to add a reference to that same cpp file to the ContosoUnitTest.
Is there an easier way to do this? Maybe a way to set a wildcard in the ContosoUnitTest project so it just slurps up all of the cpp files in the Contoso directory?
(This problem and its solution applies to any build system, but I chose Visual Studio for concreteness.)
I don’t think there’s a wildcard option in Visual Studio,¹ but even if it did, I don’t feel comfortable using it, because it means that any random file not part of the project that happens to be created in the directory will get scooped up into the unit test project.
As with many problems in computer science, this can be solved by adding another level of indirection. In this case, what you do is create a new project called ContosoCore or ContosoLib or something like that. This project includes all the cpp files and produces a library file. You then consume that library from the Contoso and ContosoUnitTest projects.
When you add a new cpp file to your project, add it to the ContosoLib project, and that will add it to both Contoso and ContosoUnitTest.
This also has the benefit that the cpp files are compiled only once (by ContosoLib), and the compiled cpp files are then consumed by the production Contoso project and the ContosoUnitTest.
¹ Current documentation says that Visual Studio IDE doesn’t support wildcards.
My solution is to add an option to run unit-tests from the application itself.
This has the added virtue that you can also have integration and end-to-end tests on the client PC.
This requires the target binary to run on the dev machine which isn't trivial in the general case (dependencies...) and also way slower when the CPU architectures don't match. You can build and fire up a VM with all the needed stuff included but it hurts your feedback loop.
We build selected parts of our (legacy) code for the host in the unit test project and run it under valgrind which also adds some value. It's...
One solution that I've used is to make a "shared project" (it's a project type) and reference it from both the main and unit test projects.
When you add new files individually to the shared project, they are automatically picked up by all projects that have the shared project as a reference. And unlike the "make a library" option, you can have different #define values so the code can be compiled differently.
Every new solution I've created...
Nice! That’s a new one for me. It surely would lose any build time benefits over making a Lib file though? That’s little benefit when building a shippable release, but it would make testing happen less often if the delay in building makes it a nuisance.
Same here. "Shared Projects" are a godsend. I also like to use them when building for different targets.
There's the main game logic shared project (which also houses the assets), and the final target specific main file (Win32, SDL, UWP, Emscripten, whatever). Works a treat!
And I'm absolutely no fan of wild cards. Neither in Visual Studio nor with makefiles. It's a chore to find out why a specific file is included when you don't want...
"I don’t think there’s a wildcard option in Visual Studio,¹ but even if it did, I don’t feel comfortable using it, because it means that any random file not part of the project that happens to be created in the directory will get scooped up into the unit test project."
I feel like this is one of those stockholm syndrome statements which gets tossed around to justify a missing feature. Used to hear the same thing...
Note that Raymond is saying *he*, personally, wouldn't be comfortable with it ("I don’t feel comfortable using it", he said). As he has told many times, this blog represents his personal views and opinions, which may be different from Microsoft's official statements.
That said, I agree with both you and Raymond. How can it be? Wildcards in projects can be a double edged sword, which depends on how you use it. You are right in that...
Converter bot to the rescue.
Clearly the upgrade solution is to evaluate the project file and the wildcard expansion and emit exclude rules for all source files that aren't in the project today.
On a related note I use makefiles a lot; and I avoid the merge problem by having one makefrag per directory that gets included into the toplevel makefile. It's also possible to use wildcards in makefiles; which I have gone back and forth about...
Executable mappings are demand-paged, though, right? The kernel loads and relocates pages as they’re first hit?