I have a project that uses a third-party library and I’ve written unit tests and added them to my test suite via gtest_discover_tests, but in order to successfully build the test target in VS I need to add the path to the third-party DLL to the PATH environment variable before running the unit test executable.
I’ve tried to use ENVIRONMENT_MODIFICATION to append to the PATH environment variable, but it doesn’t seem to do anything. I’ve tried to add a script to the TEST_INCLUDE_FILES to append to the PATH environment variable, and that doesn’t seem to do anything either. I can see the commands that in the POST_BUILD event of the test target in my solution that invokes my unit test, but the target won’t successfully “build” in MSVS without some workaround. I have several workarounds, but they’re not ideal:
I could add the path to the third-party DLL to my system environment variables before running MSVS, but the idea is that I’m using CMake to find/specify the location of the third-party library so that my project is more “portable” to other members of my team. The way the third-party library is supplied or installed may differ for other those users. I’d prefer not to have to change my system environment just so that this test case can succeed.
I can manually edit the POST_BUILD event command line and append to the PATH environment variable right after the “setlocal” command and right before the call to “cmake … -P GoogleTestAddTests.cmake” line after the MSVS solution is generated by CMake. The solution builds fine this way, but it’s annoying that CMake both knows where that third-party DLL is located (since it had to link to it), but I’m unable to inject the PATH line programmatically to the generated commands.
I can write a shell script that appends the path to the DLL to the PATH environment variable and invoke MSBUILD on the solution and everything works fine, but this solution is less friendly to other users who prefer to interact with the solution using the MSVS IDE.
I strongly recommend setting the DISCOVERY_MODE to PRE_TEST. You can add this directly to the gtest_discover_tests() call, or change the default globally by setting the CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE variable to PRE_TEST. I generally recommend the latter, there are very few cases where you would prefer to be running the executable to get the list of tests at build time rather than test time, and there are also cases where you have no alternative but to do it at test time.
Thanks, that does help by basically eliminating the offending test when the third-party library isn’t in the search path. Ideally, it would be nice if the test could be made to work since CMake needs to know the location of the third-party DLL to successfully build the project so it would seem that path should somehow be able to be passed to the tests. Per Ben’s reply, is this because gtest_discover_tests doesn’t respect the ENVIRONMENT_MODIFICATION property? I had added:
to my gtest_discover_tests call. I’m running cmake 3.27.3 and the GoogleTest documentation doesn’t specifically state that it supports ENVIRONMENT or ENVIRONMENT_MODIFICATION, I assumed that because it allows setting test properties, that it did respect that property. That’s interesting.
Note that the test discovery isn’t a test, so it doesn’t really have properties. The command would need to recognize and forward the requests as needed to the internal execute_process (that I suspect is) performed to extract the test list at build/test time.
I added a comment in that issue describing a way this can be handled now with CMake 3.29 or later. The TEST_LAUNCHER target property and its associated CMAKE_TEST_LAUNCHER variable can be used to get the desired result. Still not necessarily a clean as we might want, but it’s at least a workaround in the meantime while a more direct alternative can be discussed.