Squish Coco is mostly used for programs written in C++, but it also supports code coverage for C# programs. The preparation of a C# program for code coverage is rather simple, thanks to a Visual Studio add-in that is part of Coco.
This post is a short tutorial about the add-in and how it is used to measure the code coverage of a program.
How Coco Works
Coco works by intercepting the compilation process. Instead of the compiler, a program called CoverageScanner processes the code. By default, when code coverage is not activated, the CoverageScanner just forwards the source code to the compiler. When coverage is activated, CoverageScanner inserts statements in the source code that measure coverage and lets the built-in compiler compile the new source file. This process is called instrumentation.
The result of the instrumentation is two new files, one of them generated when the program is compiled, the other one when it runs.
The first is the instrumentation database (or .csmes file), which contains the data about the program for which you measure coverage. If the program executable is prog.exe, the .csmes file is prog.exe.csmes, and it is generated in the same directory as the executable.
The second file is the execution report (or .csexe file). It is generated when the instrumented program finishes and contains the code coverage measurements. For prog.exe, the execution report would be prog.exe.csexe. By default it is written to the work directory in which the instrumented application runs.
Visual Studio and Code Coverage
In Visual Studio, a software project can be compiled in different build modes, like Debug and Release. The build mode specifies the details of the compilation, and each build mode keeps the binaries it creates separate from those of the other build modes. Code coverage requires specific kinds of binaries, so we need a special build mode. The add-in generates it.
The code coverage build mode is a modified copy of an existing build mode. It differs from a normal build mode by some preprocessor symbols that are set by the add-in. One of them enables coverage, the rest are used to configure details of the instrumentation process. With the add-in, we do not need to use them directly. But sometimes it is good to be able to look them up in the documentation.
The details of the build mode from which the coverage mode is created does not matter. One can use Debug, Release or any other mode.
Creation of a coverage build mode
We will now create a build mode DebugCoverage, based on Debug.
In Visual Studio, the add-in can be found in the Tools menu, as the entry “Code Coverage Build Mode…”. When the menu entry is selected, a dialog window appears.
It has a number of options to select, but the most important ones are those at the top and bottom.
At the top, the “Project” entry specifies the project which should be instrumented. You can instead also select the checkbox marked “All” at its right; then the add-in creates build modes for all projects in the solution. The “Configuration” entry specifies the build mode that is copied to get the mode for code coverage.
When the add-in starts, it sets the “Project” and “Configuration” entries to the values that were active in Visual Studio. Change the “Project” entry if necessary. The “Configuration” should be “Debug“.
In the middle, the dialog contains several options to fine-tune the instrumentation, which we can ignore for the moment.
At the bottom, the “Configuration” region contains the buttons with which the add-in is put into action. For a new build mode, select the “New” radio button at the left and press the button “Create a new C# configuration“. Then the add-in dialog closes and a new build configuration is created. Its name is “DebugCoverage“, or any other name you have entered in the “Name” field. It has the same settings as the “Debug” project from which it is generated, except that in it, code coverage is enabled.
A dialog box shows up to confirm that the new build mode was created successfully.
Measuring Code Coverage
The add-in does not switch on its own to the new build mode, so you need to enable it manually. Then, you can build and run your program.
When the program is compiled, its .csmes file is created in the directory obj\DebugCoverage. When the program finishes its execution, it writes its .csexe file to the directory bin\DebugCoverage.
To view the coverage measurements, one can use the CoverageBrowser. Open the obj\DebugCoverage subdirectory and double-click the file prog.exe.csmes. The CoverageBrowser starts and loads the .csmes file. With the CoverageBrowser you now can see all the source files for prog.exe, but not yet the coverage measurements. They are contained in the file bin\DebugCoverage\prog.exe.csexe. To import them, select the menu entry “File->Load Execution Report…“. A dialog window appears where you can import the measurements.
Fine-Tuning the Code Coverage
The number of options in the middle of the add-in is a bit large to explain in a blog post, but a few of them are useful to know:
- The “Method” region in the add-in lets one select the coverage level. The list of coverage levels is cumulative, each entry including all the coverage levels above it. In most cases there are only two reasonable choices: one is to choose “MCC and MC/DC“, where one gets everything. Or, one chooses “Condition“; then, Coco inserts less complex code, and the instrumented program may run faster. (The first two options have not much influence on code complexity.)
- The option “Dynamic Type Support” influences the generated code. Dynamic types are a relatively new feature of C#, which were introduced in version 4.0. If the option is unset, Coco generates code that does not use dynamic types. This prevents compiler errors in C# versions before 4.0.
- Finally, the option “Runtime Logging” lets the instrumented program write verbose output to the standard error stream. This can be helpful, for example if it is unclear which directory the .csexe was written to or whether it was written at all.
Changing the Settings
With the add-in, one can also change the coverage settings for an existing configuration. When the options for DebugCoverage need to be changed, you can open the add-in dialog again and select “DebugCoverage” in the “Configuration” field at the top. Then, set the checkboxes in the middle as needed. At the bottom, select the “Modify” radio button, and click the button “Enable Coverage for C# Projects“. The new settings will then be written to the configuration.