<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marco Hernandez</title>
    <description>The latest articles on DEV Community by Marco Hernandez (@marcohern).</description>
    <link>https://dev.to/marcohern</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F345552%2F20d7fe77-9d56-4c8f-b5a4-2b3fb7121776.jpeg</url>
      <title>DEV Community: Marco Hernandez</title>
      <link>https://dev.to/marcohern</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcohern"/>
    <language>en</language>
    <item>
      <title>How to Measure Code Coverage in C++ with Visual Studio 2026</title>
      <dc:creator>Marco Hernandez</dc:creator>
      <pubDate>Fri, 29 May 2026 18:27:11 +0000</pubDate>
      <link>https://dev.to/marcohern/how-to-measure-code-coverage-in-c-with-visual-studio-2026-2aha</link>
      <guid>https://dev.to/marcohern/how-to-measure-code-coverage-in-c-with-visual-studio-2026-2aha</guid>
      <description>&lt;h2&gt;
  
  
  About My Code
&lt;/h2&gt;

&lt;p&gt;I'm developing a video game in C++ using SDL3 — a cross-platform library that provides access to accelerated video, audio, controllers, and more. As part of development, I'm writing unit tests using a simple custom system that works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Tests are created by inheriting from a base &lt;code&gt;Test&lt;/code&gt; class and implementing its &lt;code&gt;run&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A custom &lt;code&gt;Assert&lt;/code&gt; class handles assertions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A class called &lt;code&gt;Vgx3TestRunner&lt;/code&gt; runs all tests explicitly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no automatic test discovery — if you write a new test, you need to register it manually: add a call to it in &lt;code&gt;run()&lt;/code&gt;, and if it's a new test class, include it in &lt;code&gt;Vgx3TestRunner&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For context, this guide is written for &lt;strong&gt;Visual Studio 2026 on Windows 11&lt;/strong&gt;. The code itself should compile on Mac or Linux, but the coverage measurement steps are specific to Visual Studio 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  Measuring Coverage
&lt;/h2&gt;

&lt;p&gt;Two things need to be done:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code&gt;/PROFILE&lt;/code&gt; linker flag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run your tests and generate a coverage report.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1 — Enable the /PROFILE Linker Flag
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;/PROFILE&lt;/code&gt; flag makes your executable profilable by mapping C++ code to the underlying assembly. This is what enables coverage measurement.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Right-click your unit test project in &lt;strong&gt;Solution Explorer&lt;/strong&gt; and select &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the &lt;strong&gt;Configuration&lt;/strong&gt; dropdown to &lt;strong&gt;Debug&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;C/C++ &amp;gt; Optimization&lt;/strong&gt; and set Optimization to &lt;strong&gt;Disabled (/Od)&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;Linker &amp;gt; Advanced&lt;/strong&gt; and set &lt;strong&gt;Profile&lt;/strong&gt; to &lt;strong&gt;Yes (/PROFILE)&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Apply&lt;/strong&gt; and &lt;strong&gt;OK&lt;/strong&gt;, then do a full &lt;strong&gt;Rebuild&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Possible Build Error: Cannot Open SuchAndSuch.lib
&lt;/h4&gt;

&lt;p&gt;After enabling &lt;code&gt;/PROFILE&lt;/code&gt;, you may see a build error saying Visual Studio is &lt;strong&gt;unable to open a .lib file&lt;/strong&gt; (e.g. &lt;code&gt;SDL3.lib&lt;/code&gt;). This happens because &lt;code&gt;/PROFILE&lt;/code&gt; disables Incremental Linking, which means Visual Studio no longer infers build order automatically. Your test project now needs its dependencies — like SDL3 — to be built first, but Visual Studio doesn't know that yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tell Visual Studio about the dependency:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Right-click your test project in Solution Explorer and select &lt;strong&gt;Add &amp;gt; Reference...&lt;/strong&gt; (or &lt;strong&gt;Build Dependencies &amp;gt; Project Dependencies&lt;/strong&gt;, depending on your layout).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;strong&gt;Projects&lt;/strong&gt; tab, check the boxes next to &lt;strong&gt;SDL3&lt;/strong&gt;, &lt;strong&gt;SDL3_image&lt;/strong&gt;, and any other relevant dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;OK&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Tell the linker where to find the output .lib files:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Right-click your test project and go to &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;strong&gt;Configuration Properties &amp;gt; General&lt;/strong&gt;, note the &lt;strong&gt;Output Directory&lt;/strong&gt; path — typically something like &lt;code&gt;$(SolutionDir)$(Platform)\$(Configuration)\&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;Linker &amp;gt; General &amp;gt; Additional Library Directories&lt;/strong&gt; and paste that same path macro there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Apply&lt;/strong&gt; and &lt;strong&gt;OK&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now do a &lt;strong&gt;Clean Rebuild&lt;/strong&gt; — your project should compile and run correctly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 — Run Tests and Generate a Coverage Report
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;/PROFILE&lt;/code&gt; enabled, you can use the Visual Studio 2026 built-in tool &lt;strong&gt;Microsoft.CodeCoverage.Console.exe&lt;/strong&gt; to run your binary and measure coverage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open a terminal in Visual Studio via &lt;strong&gt;View &amp;gt; Terminal&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From your solution directory, run:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Microsoft.CodeCoverage.Console.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;collect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\x64\Debug\test.exe&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;test.exe&lt;/code&gt; with your test project's binary name if it differs.&lt;/p&gt;

&lt;p&gt;Your tests will run as normal, and a file called &lt;strong&gt;output.coverage&lt;/strong&gt; will be generated. To view it, drag and drop it into Visual Studio from the Explorer window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphxzijt6ulypvto42idp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphxzijt6ulypvto42idp.png" alt="Code coverage report, but it is noisy!" width="752" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The report shows what percentage of your code was executed during the test run — 100% means full coverage, 0% means none. You'll notice it also measures coverage for your test infrastructure itself, which is usually just noise. To filter that out, you can add a &lt;strong&gt;.runsettings&lt;/strong&gt; configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- .runsettings --&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;RunSettings&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;DataCollectionRunSettings&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;DataCollectors&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;DataCollector&lt;/span&gt;
    &lt;span class="na"&gt;friendlyName=&lt;/span&gt;&lt;span class="s"&gt;"Code Coverage"&lt;/span&gt; &lt;span class="na"&gt;uri=&lt;/span&gt;&lt;span class="s"&gt;"datacollector://Microsoft/CodeCoverage/2.0"&lt;/span&gt;   &lt;span class="na"&gt;assemblyQualifiedName=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Configuration&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;CodeCoverage&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;Sources&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Exclude&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Don't measure coverage for the tests themselves --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;SourcePath&amp;gt;&lt;/span&gt;.*src\.tests.*&lt;span class="nt"&gt;&amp;lt;/SourcePath&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/Exclude&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/Sources&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;Functions&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;Exclude&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Don't measure coverage of the Assert class --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Function&amp;gt;&lt;/span&gt;.*Assert::.*&lt;span class="nt"&gt;&amp;lt;/Function&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/Exclude&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/Functions&amp;gt;&lt;/span&gt;

     &lt;span class="nt"&gt;&amp;lt;/CodeCoverage&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Configuration&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/DataCollector&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/DataCollectors&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/DataCollectionRunSettings&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/RunSettings&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in place, the report will focus on the code that actually matters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsekkj716ii6nfwn6yv8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsekkj716ii6nfwn6yv8i.png" alt="Code coverage report, now noiseless, that's better!" width="757" height="330"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Aim for around &lt;strong&gt;80% coverage&lt;/strong&gt; — that's generally a healthy target. You don't need to chase 100%. Good luck!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>microsoft</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
