Running CTests in a Juce CMake project

I’m adding a sub-folder for test files to my main project. The sub-folder has its own CMakeLists.txt file which adds the tests. But in those files in the sub-directory, I can’t include the normal JuceHeader.h.

CMakeLists.txt:

// all the usual juce CMake setup here
juce_generate_juce_header(${CMAKE_PROJECT_NAME})
include (CTest)
enable_testing()
add_subdirectory(tests)

tests/CMakeLists.txt:

add_executable(My_Tests run_all_tests.cpp)
add_test(test_my_app My_Tests)

tests/run_all_tests.cpp:

#include <JuceHeader.h>        // error
#include <../JuceHeader.h>     // also error

int main()
{
	return 0;
}

Can anyone spot what the problem is? I’ve tried the rebuilding trick mentioned here, but with no luck. I figure it’s probably something simple though.

juce_generate_juce_header generates a header for one specific target, added with juce_add_plugin, juce_add_gui_app, or juce_add_console_app.

To use a JUCE header in your test executable, you should add the test target with juce_add_console_app instead of add_executable, and should additionally call juce_generate_juce_header(My_Tests).

Thanks reuk, it’s working now. I’m still struggling to get CTests working though, since main() never seems to get called for some reason. Does anyone have any examples up on github of using CMake, CTest and juce::UnitTestRunner?

I don’t really use CTest, but I think it should be enough to just call enable_testing() and add_test() in your CMakeLists.

Have you read through the docs for add_test?

https://cmake.org/cmake/help/latest/command/add_test.html#command:add_test

The problem that I’m having is that add_test() just runs the last built version of the test, but doesn’t build the new version when I change the run_all_tests.cpp file.

I tried adding a command to add_tests(), based on this SO page.

add_test(test_build
  "${CMAKE_COMMAND}"
  --build "${CMAKE_BINARY_DIR}"
  --config "$<CONFIG>"
  --target ${TEST_PROJECT_NAME}
)

Now CMake builds run_all_tests.cpp, but it does not run the file (it just says it succeeded because it built the file, but the tests themselves haven’t been run.

I’m back again with more CMake troubles.

I ended up abandoning CTests and just running tests within my app’s native environment. My app has its own console, so it seemed to make sense. The basic idea was to bundle all of my code minus the JUCEApplication class into a new library (let’s call it CoreLibrary). Then I have two new CMake targets which link CoreLibrary. Both of them have a different JUCEApplication class and main() function, one to load the normal app and the other to load the testing variation. This actually compiles; however, it throws Intellisense off completely, and my error console is littered with errors because it thinks it doesn’t recognize JUCE. Even though these error messages are “wrong”, it makes it difficult for me to proceed, because finding the real errors is now next to impossible.

I know that this is a really boring post, and also that my code is really messy (the only approach I know with CMake is to hack at it until it work). But would someone mind taking a quick look over my code and giving me some feedback? I’m not even sure if it’s a problem with my CMake setup or if it’s a bug with Visual Studio, so it’s really hard to me to find help about this online.

Here’s my basic folder structure:

  • MainFolder
  • launch_app.cpp (includes JUCEApplication class)
  • CMakeLists.txt 1: to load the main app
  • Source
    • All source files…
    • CMakeLists.txt 2: To load the CoreLibrary
  • Testing
    • run_all_tests.cpp (includes JUCEApplication class)
    • Other testing files…
    • CMakeLists.txt 3: to load the testing app

And here’s a shortened version of my CMakeLists files:

CMakeLists.txt 1: (in main folder)


project(MyApp)

add_subdirectory(JUCE)

juce_add_plugin(${CMAKE_PROJECT_NAME}
 # ...
)

juce_generate_juce_header(${CMAKE_PROJECT_NAME})

target_sources(${CMAKE_PROJECT_NAME}
    PRIVATE
launch_app.cpp
)

add_subdirectory(Source)

target_link_libraries(${CMAKE_PROJECT_NAME}
    PUBLIC
        juce::juce_audio_utils
        tracktion_engine
        juce::juce_recommended_config_flags
        juce::juce_recommended_lto_flags
        juce::juce_recommended_warning_flags
       #...
)

add_subdirectory(Testing)

CMakeLists.txt 2: (in Source folder)

project(CoreLibrary)    # Am I right to have a new project() call here?

target_sources(${CMAKE_PROJECT_NAME}
    PRIVATE
    # all my files.,.
)

add_library(Context_Core_Lib
    SHARED
    # all my files again...
)

target_link_libraries(${CMAKE_PROJECT_NAME}
    PUBLIC

        juce::juce_audio_utils
        tracktion_engine    
        juce::juce_recommended_config_flags
        juce::juce_recommended_lto_flags
        juce::juce_recommended_warning_flags)

CMakeLists.txt 3 (inside Testing folder)


set(TEST_PROJECT_NAME Context_Tests)
set(TRACEDESIGNTIME true) # ??

juce_add_plugin(${TEST_PROJECT_NAME}
    # ...
    PRODUCT_NAME "Context Tester")

juce_generate_juce_header(${TEST_PROJECT_NAME})

target_sources(${TEST_PROJECT_NAME} PRIVATE
    #...
    run_all_tests.cpp)

target_link_libraries(${TEST_PROJECT_NAME}
    PUBLIC
        juce::juce_audio_utils
        tracktion_engine
        ${CMAKE_PROJECT_NAME}
        juce::juce_recommended_config_flags
        juce::juce_recommended_lto_flags
        juce::juce_recommended_warning_flags)