简体   繁体   中英

How to run a .dll test suite with CMake and Microsoft Unit Test Framework

In a CMake project, I generated a C++/CLI project and a testing SHARED library according to this post

CMake for integrated Microsoft Unit Testing Framework (VS2017)

I am trying to run the tests, but neither Visual Studio or Visual Studio Code are able to discover my tests.

The unique difference is that I am created a test subfolder as a CMake subproject, with it's respective CMakeLists.txt, but is exactly the same config.

What I am doing bad?

Thanks.

Analysis of the linked question

The answer to the question you linked has several problems:

  • It uses some very old school CMake techniques ( include_directories() + link_directories() ). Please use some more recent 3.x version of CMake and apply modern CMake techniques [1][2] .
  • Also, you should not pass the SHARED / STATIC keyword to add_library() and rather use the BUILD_SHARED_LIBS variable to control whether to build shared or static binaries.
  • It is incomplete. You need to call add_test() to create a test for ctest , otherwise neither ctest nor an IDE can be aware of your unit tests. Alsoenable_testing() needs to be called in the top-level project, otherwise add_test() has no effect.

Minimal working example

CMakeLists.txt :

cmake_minimum_required(VERSION 3.21)
project(so70759660)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
  enable_testing()
  add_subdirectory(tests)
endif()

tests/CMakeLists.txt :

find_package(MSUnitTestFramework REQUIRED)
find_program(VSTest_EXECUTABLE NAMES vstest.console.exe REQUIRED)

add_library(mytest)
target_sources(mytest PRIVATE Mytest.cpp)
target_link_libraries(mytest PRIVATE MSUnitTestFramework::MSUnitTestFramework)
add_test(NAME mytest COMMAND "${VSTest_EXECUTABLE}" "$<TARGET_FILE:mytest>")

cmake/FindMSUnitTestFramework.cmake :

add_library(MSUnitTestFramework::MSUnitTestFramework SHARED IMPORTED)
set_target_properties(MSUnitTestFramework::MSUnitTestFramework PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "$ENV{VCInstallDir}Auxiliary/VS/UnitTest/include"
  IMPORTED_IMPLIB "$ENV{VCInstallDir}Auxiliary/VS/UnitTest/lib/x86/Microsoft.VisualStudio.TestTools.CppUnitTestFramework.lib"
)
set(MSUnitTestFramework_FOUND TRUE)

Notes:

  • Using an IMPORTED target and linking it via target_link_libraries() is the modern alternative to include_directories() / include_libraries() .
  • The FindMSUnitTestFramework module is responsible for locating and creating this imported target. Please note that the example that I provided is rather hard-coded and not very "smart" at finding the library and maybe considering things like different Visual Studio versions or target architectures. You may need to improve this.

tests/MyTest.cpp :

#include <CppUnitTest.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

TEST_CLASS(Class1) {
  public:
    TEST_METHOD(Method1) { Assert::AreEqual(0, 0); }
    TEST_METHOD(Method2) { Assert::AreNotEqual(0, 42); }
};

CMakePresets.json :

{
    "version": 3,
    "configurePresets": [
        {
            "name": "vs2022",
            "generator": "Visual Studio 17 2022",
            "binaryDir": "${sourceDir}/build/${presetName}",
            "cacheVariables": {
                "CMAKE_C_COMPILER": "cl",
                "CMAKE_CXX_COMPILER": "cl",
                "BUILD_TESTING": "ON",
                "BUILD_SHARED_LIBS": "ON"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "vs2022",
            "configurePreset": "vs2022"
        }
    ],
    "testPresets": [
        {
            "name": "vs2022",
            "configurePreset": "vs2022",
            "configuration": "Debug"
        }
    ]
}

Compatibility

I was only able to get this running by using a Visual Studio generator in combination with a MSVC toolchain. For other generators (Ninja, Make, etc.) I always got a linker error, but could not figure out what the cause is.

VS Code does display the test in the test explorer (you probably require the CMake Test Explorer extension), but Visual Studio does not. I suspect this is a general problem, that VS only recognizes the add_test(<name> <command> <args>) signature but not add_test(NAME <name> COMMAND <command>...) with multi-config generators. Here is a related bug report . But unfortunately, the first signature won't suffice, because it does not support generator expressions like $<TARGET_FILE:...> .

Personal opinion

IMHO if you have a choice which unit testing framework/library to use, I would recommend you agains using Microsoft Unit Test Framework for several reasons:

  • You restrict yourself to a MSVC toolchain.
  • It is rather tailors towards Visual Studio/MSBuild. Itegrating it into any other build system is rather tedious.
  • AFAIK you can't even install it separately, but only install it as part of Visual Studio.
  • It is not cross-platform, so you will always be stuck with Windows.

My recommendation would be to use something cross-platform that can be used with different compilers/toolchains, is possibly open-source and provides some better integration with other build systems. Examples include GTest, Catch, Boost.Test, etc. With those, you could use a single-config generator like eg Ninja and then the test explorer in Visual Studio should discover them. emphasized text

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM