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
docsfolder 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 thejuce::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
UnitTestRunnerproject in the JUCE repo. The most important thing to notice is theJUCE_UNIT_TESTS=1compile 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 forJUCE_UNIT_TESTSto 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!
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!
Yes, I think this advice still holds.
thank u!
