The release of C/C++test 2020.1 introduces the ability to integrate C/C++test with CMake for static analysis and unit testing. This post focuses on how to use Parasoft C/C++test with CMake-based projects for unit testing.
Unit testing is more complicated to integrate into the development process than static analysis. In the end, the executable binary file must be created. This is especially problematic for large and complex projects that are composed of multiple libraries and executables.
The compile-info JSON file, which we use for the static analysis, is not enough. It doesn’t provide the important information about the structure of the project—which files are included in which binaries and what should be tested together.
To enable easy integration of Parasoft C/C++test unit testing into CMake-based projects, the 2020.1 release introduces a CMake extension, which allows defining unit testing targets for C/C++test. These targets automatically generate the C/C++test project files that can be used for creating, running, and maintaining unit tests.
The intention of this extension is to enable users to define the entire infrastructure that’s required for Parasoft C/C++test unit testing together with their regular targets in the CMake configuration files.
Let’s see how it works using an example using the C/C++test Professional – Eclipse-based tool, which features a rich UI. Download and install the 2020.1 release, if you haven’t already.
In the main installation directory of C/C++test Professional, you can find the CMake extension with accompanying example. See the following directory: <install dir>integration/cmake.
For our experiments I recommend copying the integration/cmake folder out from the installation to your preferred location. The structure of the example is shown below:
The app folder contains the “executable” target. The modules folder with its three subfolders (mod1, mod2 and mod3) represents static libraries used to link with the executable. Additionally, the cmake folder contains the C/C++test extension to CMake. You may want to copy this folder to your real project in order to use this extension.
This simplified structure paints a picture of typical challenges teams trying to implement unit testing face: How to divide the entire project into testable chunks, representing groups of files that logically belong together.
In most cases, developers will not want to execute unit tests against one blob binary created by compilation of all the files from an entire project. Users will most likely be interested in adding the test cases for the same binary targets (executables and libraries) they have defined in the project.
Before discussing the details of the configuration syntax let’s see how it works using the provided example.
1. In the top-level directory where app folder is located, create a build directory, cd into it, and call a build scripts generation, like below:
2. After CMake is done with the build scripts (makefiles) generation, call make to build the example project:
3. Start C/C++test professional (the cpptest executable in the installation folder). Select an empty workspace, use “File Menu -> Import … -> Existing Projects into Workspace” and select “root directory” to be the main folder where you copied the example. Wizard will recursively scan the selected folder and find all the projects that were automatically generated. If you see something like below, you can click “Finish”.
Eclipse will import all the projects and you will have a fresh workspace ready for your unit testing. You don’t have to do anything else to start adding and running the test cases and working to improve your code coverage.
4. In the project navigator, select all three projects, right click and use “Parasoft -> Test Using -> Builtin -> Unit Testing -> Generate Unit Tests” test configuration to automatically generate the test cases. Once tests are generated, execute “Run Unit Tests” configuration from the same location.
With these simple four steps, you prepared the project infrastructure for unit testing. The team is now all set to start crunching the test cases.
In addition to regular build targets, the CMakeLists.txt files contain unit testing targets. When generating the build scripts with cmake, C/C++test project files are also automatically generated. Later during the build process additional build-data-files, which are required by C/C++test projects, are automatically generated.
Everything that is needed to define the structure of the unit testing projects is kept inside CMakeLists.txt files. The team does not need to maintain any additional configuration files. Everything is nice and clean. The project can be checked out, build scripts and C/C++test projects can be generated, tests can be added and checked in together with the source code, and full testing can be performed in the CI.
Let’s take a closer look at the C/C++test CMake extension and how it helps in defining the test projects infrastructure. Open the modules/mod1/CMakeLists.txt file. You should see something like below:
In the first six lines, you can see the regular target definition. Here we are defining a simple library target, with one source file mod1.cpp, and include files directory. This is what you will typically see in your CMake projects.
In the line 11, however, we have a new CMake function that is provided with C/C++test extension. This function allows you to define the unit testing target, which generates all required C/C++test project files. You can find the full description of this function in the integrations/cmake/README.md. In this specific example, the following is done:
This simple target definition is enough to generate a unit testing project for Parasoft C/C++test. Project files will be generated in the location of CMakeLists.txt file, which is probably the most convenient. If you prefer, you can generate the project files outside of the source tree and avoid any merging issues. This is shown in app/CMakeLists.txt:
For more details, review the following files from the <install dir>/integrations/cmake directory:
Here are the important points about the extension.
Product Manager for Parasoft's embedded testing solutions, Miroslaw's specialties include C/C++, RTOSes, static code analysis, unit testing, managing software quality for safety critical applications, and software compliance to safety standards.