Juce Unit Tests and CMake

I changed my app over to use CMake and also saw that juce has unit testing capabilities. Has anyone used the juce unit test stuff in conjunction with CMake? How would I go about setting that up? New to CMake and testing in general so kind of lost.

I think I’d recommend an approach like this:

  • Put the code you want to test into a ‘module’. There’s documentation for the module format in the docs folder in the JUCE repo.
  • Add the module to your CMake project with juce_add_module.
  • Link your app against the module using target_link_libraries, in the same way that you’d link a JUCE module (although without the juce:: prefix). Try building the app to check that the new module is working.
  • Now you can create a new console app target, and link it against your new module. For this bit, I’d recommend looking at the UnitTestRunner project in the JUCE repo. The most important thing to notice is the JUCE_UNIT_TESTS=1 compile definition. This flag is only enabled for the unit test runner, which prevents the unit test code getting built into a ‘normal’ target. You can also search the repo for JUCE_UNIT_TESTS to see example unit test classes and their surrounding #ifdefs.

Thanks! I’ll give this a shot

Quick question. One thing I noticed when setting up my CMakeLists and following the Gui_App CMake example, is that when I use target_link_libraries to link the juce_modules, it only works if it remove the juce:: from the module names, whereas in the docs it has juce:: in front of them. Is this due to the fact that I have included JUCE using add_subdirectory? JUCE is a git submodule in my project so I have used the add subdirectory command:

cmake_minimum_required(VERSION 3.16)

project(APP VERSION 0.0.1)


add_subdirectory(JUCE)

juce_add_gui_app(APP
    # VERSION ...                       # Set this if the app version is different to the project version
    # ICON_BIG ...                      # ICON_* arguments specify a path to an image file to use as an icon
    # ICON_SMALL ...
    # DOCUMENT_EXTENSIONS ...           # Specify file extensions that should be associated with this app
    # COMPANY_NAME ...                  # Specify the name of the app's author
    PRODUCT_NAME "APP"                  # The name of the final executable, which can differ from the target name
)        

target_sources(APP PRIVATE
... bunch of files here
...
...
)

target_compile_definitions(APP PRIVATE
    # JUCE_WEB_BROWSER and JUCE_USE_CURL would be on by default, but you might not need them.
    JUCE_WEB_BROWSER=0  # If you remove this, add `NEEDS_WEB_BROWSER TRUE` to the `juce_add_gui_app` call
    JUCE_USE_CURL=0     # If you remove this, add `NEEDS_CURL TRUE` to the `juce_add_gui_app` call
    JUCE_APPLICATION_NAME_STRING="$<TARGET_PROPERTY:APP,JUCE_PROJECT_NAME>"
    JUCE_APPLICATION_VERSION_STRING="$<TARGET_PROPERTY:APP,JUCE_VERSION>"
)

target_link_libraries(APP PRIVATE
    juce_audio_basics
    juce_audio_devices
    juce_audio_formats
    juce_audio_processors
    juce_audio_utils
    juce_core
    juce_data_structures
    juce_dsp
    juce_events
    juce_graphics
    juce_gui_basics
    juce_gui_extra
    tracktion_engine
)

The juce:: prefixes definitely should work when using JUCE as a subdirectory. I’m surprised the snippet works at all, though: the juce_add_gui_app function is defined in the JUCE subdirectory, so I’m not sure how you’re calling it before the add_subdirectory call. Do the juce:: prefixes work if you move the add_subdirectory call directly after the project call? Also, note that only the JUCE modules will use the juce:: prefix. tracktion_engine will not.

Whoops! I must have flipped the order of those when I copied it in to my comment. the add_subdirectory call is definitely before the juce_add_gui_app. I just tried adding the juce:: back in to the module names (minus tracktion_engine) and it seems to be working fine. This occurred yesterday and I cant quite recall what the error was, but its possible I had something in my CMake file that was out of order or something and fixed it without realizing. Thank you!

1 Like

Sorry but I have another question. It looks like the juce_modules include the unit tests inside the module itself. Is this what you would recommend doing? Or would you recommend having a special tests/ directory outside of the module and putting all tests in there and including the module as needed? Or some other way? Ive seen lots of different structures for testing and was just curious about what you recommend .

To be honest I can’t think of a really compelling reason to prefer either way. Including the tests directly in the module might make it easier to develop features/tests in parallel. However, putting the tests in separate files may allow modifying the tests in isolation without having to rebuild the code under test at the same time. If the code you’re testing takes a long time to build, this may be a desirable property.

okay thank you! I was able to refactor my code into a module and then create a console project that builds a unit test runner as you mentioned in your earlier posts. Thank you for helping. Being new to CMake I probably would not have been able to figure this out without your help so I really appreciate it!