Přizpůsobení analýzy pokrytí kódu

Pokrytí kódu ve výchozím nastavení analyzuje všechna sestavení řešení načtená během testů jednotek. Doporučujeme použít toto výchozí chování, protože ve většině případů funguje dobře. Další informace najdete v tématu Použití pokrytí kódu k určení, kolik kódu je testováno.

Pokud chcete vyloučit testovací kód z výsledků pokrytí kódu a zahrnout pouze kód aplikace, přidejte ExcludeFromCodeCoverageAttribute do testovací třídy atribut.

Chcete-li zahrnout sestavení, která nejsou součástí vašeho řešení, získejte soubory .pdb pro tato sestavení a zkopírujte je do stejné složky jako soubory .dll sestavení.

Spustit soubor nastavení

Soubor nastavení spuštění je konfigurační soubor používaný nástroji pro testování částí. Rozšířené nastavení pokrytí kódu se zadává v souboru .runsettings .

Pokud chcete přizpůsobit pokrytí kódu, postupujte takto:

  1. Přidejte do svého řešení soubor nastavení spuštění. V Průzkumník řešení v místní nabídce vašeho řešení zvolte Přidat>novou položku a vyberte Soubor XML. Uložte soubor s názvem, jako je CodeCoverage.runsettings.

    Pokud nevidíte všechny šablony položek, zvolte Zobrazit všechny šablony a pak zvolte šablonu položky.

  2. Přidejte obsah z ukázkového souboru na konec tohoto článku a pak ho upravte podle svých potřeb, jak je popsáno v následujících částech.

  3. Vyberte soubor nastavení spuštění.

    Počínaje sadou Visual Studio 2019 verze 16.4 můžete automaticky zjistit soubor nastavení spuštění v kořenovém adresáři projektu. V opačném případě v nabídce Test zvolte Konfigurovat spuštění Nastavení a pak zvolte Vybrat soubor runsettings pro řešení. Pokud chcete zadat soubor nastavení spuštění pro spouštění testů z příkazového řádku, přečtěte si téma Konfigurace testů jednotek.

    Když vyberete Analyzovat pokrytí kódu, informace o konfiguraci se načtou ze souboru nastavení spuštění.

    Tip

    Všechny předchozí výsledky pokrytí kódu a barevné barvy kódu se při spuštění testů nebo aktualizaci kódu automaticky skryjí.

    Pokud chcete vlastní nastavení vypnout a zapnout, zrušte výběr nebo vyberte soubor v nabídce Test .

    Pokud chcete vybrat soubor nastavení spuštění, v nabídce Test zvolte Vybrat Nastavení Soubor. Pokud chcete zadat soubor nastavení spuštění pro spouštění testů z příkazového řádku, přečtěte si téma Konfigurace testů jednotek.

    Když vyberete Analyzovat pokrytí kódu, informace o konfiguraci se načtou ze souboru nastavení spuštění.

    Tip

    Všechny předchozí výsledky pokrytí kódu a barevné barvy kódu se při spuštění testů nebo aktualizaci kódu automaticky skryjí.

    Pokud chcete vlastní nastavení vypnout a zapnout, zvolte Test, Konfigurovat spuštění Nastavení a zrušte výběr nebo vyberte název souboru.

Cesty hledání symbolů

Pokrytí kódu vyžaduje soubory symbolů (soubory PDB ) pro sestavení. Pro sestavení sestavená vaším řešením se soubory symbolů obvykle nacházejí společně s binárními soubory a pokrytí kódu funguje automaticky. V některých případech můžete chtít do analýzy pokrytí kódu zahrnout odkazovaná sestavení. V takových případech nemusí soubory .pdb sousedit s binárními soubory, ale můžete zadat cestu hledání symbolů v souboru .runsettings .

<SymbolSearchPaths>
      <Path>\\mybuildshare\builds\ProjectX</Path>
      <!--More paths if required-->
</SymbolSearchPaths>

Poznámka:

Řešení symbolů může nějakou dobu trvat, zejména při použití vzdáleného umístění souboru s mnoha sestaveními. Proto zvažte kopírování souborů .pdb do stejného místního umístění jako binární soubory (.dll a .exe).

Zahrnutí nebo vyloučení sestavení a členů

Do analýzy pokrytí kódu můžete zahrnout nebo vyloučit sestavení nebo konkrétní typy a členy. Pokud je oddíl Include prázdný nebo vynechán, jsou zahrnuta všechna sestavení, která jsou načtena a mají přidružené soubory PDB. Pokud sestavení nebo člen odpovídá klauzuli v oddílu Exclude , je vyloučena z pokrytí kódu. Oddíl Vyloučit má přednost před oddílem Zahrnout : pokud je sestavení uvedené v zahrnutí i vyloučení, nebude zahrnuta v pokrytí kódu.

Například následující xml vylučuje jedno sestavení zadáním jeho názvu:

<ModulePaths>
  <Exclude>
   <ModulePath>.*Fabrikam.Math.UnitTest.dll</ModulePath>
   <!-- Add more ModulePath nodes here. -->
  </Exclude>
</ModulePaths>

Následující příklad určuje, že do pokrytí kódu by mělo být zahrnuto pouze jedno sestavení:

<ModulePaths>
  <Include>
   <ModulePath>.*Fabrikam.Math.dll</ModulePath>
   <!-- Add more ModulePath nodes here. -->
  </Include>
</ModulePaths>

Následující tabulka ukazuje různé způsoby, jak lze sestavení a členy spárovat s zahrnutím nebo vyloučením z pokrytí kódu.

Prvek XML Co odpovídá
ModulePath Odpovídá sestavením určeným názvem sestavení nebo cestou k souboru.
CompanyName Odpovídá sestavení podle atributu Společnost .
Publickeytoken Odpovídá podepsaným sestavením tokenem veřejného klíče.
Source Odpovídá prvkům podle názvu cesty zdrojového souboru, ve kterém jsou definované.
Atribut Odpovídá prvkům, které mají zadaný atribut. Zadejte úplný název atributu, například <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>.

Pokud atribut vyloučíteCompilerGeneratedAttribute, kód, který používá jazykové funkce, jako asyncjsou , awaityield returna automaticky implementované vlastnosti jsou vyloučeny z analýzy pokrytí kódu. Chcete-li vyloučit skutečně vygenerovaný kód, vylučte GeneratedCodeAttribute pouze atribut.
Function Odpovídá procedurám, funkcím nebo metodám podle plně kvalifikovaného názvu, včetně seznamu parametrů. Část názvu můžete také spárovat pomocí regulárního výrazu.

Příklady:

Fabrikam.Math.LocalMath.SquareRoot(double); (C#)

Fabrikam::Math::LocalMath::SquareRoot(double) (C++)

Formáty pokrytí kódu

Ve výchozím nastavení se shromažďuje a ukládá pokrytí kódu do .coverage souboru. Pokrytí můžete také shromažďovat pomocí jiných formátů, včetně Xml a Cobertura. Různé formáty můžou být užitečné v různých editorech a kanálech. To můžete povolit v runsettings přidáním <Format>Cobertura</Format> nebo <Format>Xml</Format> v konfigurační části DataCollector v souboru runsettings. Tento formát lze zobrazit v okně výsledků pokrytí kódu v sadě Visual Studio Enterprise.

Můžete také zadat různé formáty z příkazového řádku tak, že ho zadáte do souboru runsettings nebo ho zadáte v parametru. Například příkazový řádek dotnet používá dotnet test --collect:"Code Coverage;Format=Cobertura". Pro vstest použití vstest.console.exe /collect:"Code Coverage;Format=Cobertura". Parametr collect přepíše formát zadaný v runsettings.

Statická a dynamická nativní instrumentace

V sadě Visual Studio 2022 verze 17.2 jsme přidali možnost instrumentace nativního binárního souboru staticky (na disku). V předchozích verzích jsme podporovali pouze dynamickou instrumentaci, která často nebyla schopna instrumentovat metody. Statická nativní instrumentace je stabilnější a doporučuje se. Statická nativní instrumentace vyžaduje povolení možnosti propojení /PROFILE pro všechny nativní projekty, pro které potřebujete kolekci pokrytí kódu.

Nativní statickou instrumentaci můžete povolit povolením nativní statické instrumentace pokrytí kódu ve verzi Preview funkce Nástroje > Možnosti > prostředí > Ve verzi Preview.

Nativní statickou instrumentaci můžete také povolit v sadách runsettings přidáním <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation> pod <CodeCoverage> značky. Tuto metodu použijte pro scénáře příkazového řádku.

Ve výchozím nastavení je dynamické nativní instrumentace vždy povolená. Pokud je povolená statická i dynamická instrumentace, visual Studio se pokusí instrumentovat váš kód C++staticky, ale pokud to není možné (například pokud /PROFILE není povolená možnost propojení), použije se dynamická instrumentace. Dynamické nativní instrumentace můžete v runsettings úplně zakázat přidáním <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation> do části <CodeCoverage>.

Pokud je povolena statická nativní instrumentace, budou nativní binární soubory instrumentovány a nahrazeny na disku před provedením testu. Po provedení testu se obnoví původní binární soubory. Obnovení původních souborů v sadách runsettings můžete zakázat přidáním <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore> pod <CodeCoverage> značku. To může být užitečné zejména ve scénářích CI.

Pokud je povolená statická nativní instrumentace, Visual Studio vyhledá a instrumentuje všechny nativní binární soubory v adresáři, kde se nachází testovací binární soubor. Můžete zadat další adresáře, ve kterých se mají prohledávat binární soubory. Následující příklad určuje, že všechny nativní binární soubory z C:\temp a jeho podadresáře by měly být instrumentovány s výjimkou souborů končících na Fabrikam.Math.dll.

<ModulePaths>
  <IncludeDirectories>
    <Directory Recursive="true">C:\temp</Directory>
  </IncludeDirectories>
  <Exclude>
    <ModulePath>.*Fabrikam.Math.dll</ModulePath>
  </Exclude>
</ModulePaths>

Regulární výrazy

Zahrnout a vyloučit uzly používají regulární výrazy, které nejsou stejné jako zástupné kóty. Ve shodách se nerozlišují velká a malá písmena. Zde je několik příkladů:

  • .* odpovídá řetězci libovolných znaků.

  • \. odpovídá tečkě "."

  • \( \) odpovídá závorkách "( )"

  • \\ odpovídá oddělovači cesty k souboru \.

  • ^ odpovídá začátku řetězce.

  • $ odpovídá konci řetězce.

Následující xml ukazuje, jak zahrnout a vyloučit konkrétní sestavení pomocí regulárních výrazů:

<ModulePaths>
  <Include>
    <!-- Include all loaded .dll assemblies (but not .exe assemblies): -->
    <ModulePath>.*\.dll$</ModulePath>
  </Include>
  <Exclude>
    <!-- But exclude some assemblies: -->
    <ModulePath>.*\\Fabrikam\.MyTests1\.dll$</ModulePath>
    <!-- Exclude all file paths that contain "Temp": -->
    <ModulePath>.*Temp.*</ModulePath>
  </Exclude>
</ModulePaths>

Následující kód XML ukazuje, jak pomocí regulárních výrazů zahrnout a vyloučit konkrétní funkce:

<Functions>
  <Include>
    <!-- Include methods in the Fabrikam namespace: -->
    <Function>^Fabrikam\..*</Function>
    <!-- Include all methods named EqualTo: -->
    <Function>.*\.EqualTo\(.*</Function>
  </Include>
  <Exclude>
    <!-- Exclude methods in a class or namespace named UnitTest: -->
    <Function>.*\.UnitTest\..*</Function>
  </Exclude>
</Functions>

Upozorňující

Pokud v regulárním výrazu dojde k chybě, například neuskutečněné nebo nezávorky, analýza pokrytí kódu se nespustí.

Další informace o regulárních výrazech naleznete v tématu Použití regulárních výrazů v sadě Visual Studio.

Ukázkový soubor s příponou .runsettings

Zkopírujte tento kód a upravte ho tak, aby vyhovoval vašim potřebám.

<?xml version="1.0" encoding="utf-8"?>
<!-- File name extension must be .runsettings -->
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
        <Configuration>
          <CodeCoverage>
<!--
Additional paths to search for .pdb (symbol) files. Symbols must be found for modules to be instrumented.
If .pdb files are in the same folder as the .dll or .exe files, they are automatically found. Otherwise, specify them here.
Note that searching for symbols increases code coverage runtime. So keep this small and local.
-->
<!--
            <SymbolSearchPaths>
                   <Path>C:\Users\username\source\repos\ProjectX</Path>
                   <Path>\\mybuildshare\builds\ProjectX</Path>
            </SymbolSearchPaths>
-->

<!--
About include/exclude lists:
Empty "Include" clauses imply all; empty "Exclude" clauses imply none.
Each element in the list is a regular expression (ECMAScript syntax). See /visualstudio/ide/using-regular-expressions-in-visual-studio.
An item must first match at least one entry in the include list to be included.
Included items must then not match any entries in the exclude list to remain included.
-->

            <!-- Match assembly file paths: -->
            <ModulePaths>
              <Include>
                <ModulePath>.*\.dll$</ModulePath>
                <ModulePath>.*\.exe$</ModulePath>
              </Include>
              <Exclude>
                <ModulePath>.*CPPUnitTestFramework.*</ModulePath>
              </Exclude>
              <!-- Specifies additional list of directories where binaries static native instrumentation should be searched. -->
              <IncludeDirectories>
                <Directory Recursive="true">C:\b59fb11c-1611-4562-9a2b-c35719da65d3</Directory>
              </IncludeDirectories>
            </ModulePaths>

            <!-- Match fully qualified names of functions: -->
            <!-- (Use "\." to delimit namespaces in C# or Visual Basic, "::" in C++.)  -->
            <Functions>
              <Exclude>
                <Function>^Fabrikam\.UnitTest\..*</Function>
                <Function>^std::.*</Function>
                <Function>^ATL::.*</Function>
                <Function>.*::__GetTestMethodInfo.*</Function>
                <Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
                <Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
              </Exclude>
            </Functions>

            <!-- Match attributes on any code element: -->
            <Attributes>
              <Exclude>
                <!-- Don't forget "Attribute" at the end of the name -->
                <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>
                <Attribute>^System\.Diagnostics\.DebuggerNonUserCodeAttribute$</Attribute>
                <Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
                <Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
              </Exclude>
            </Attributes>

            <!-- Match the path of the source files in which each method is defined: -->
            <Sources>
              <Exclude>
                <Source>.*\\atlmfc\\.*</Source>
                <Source>.*\\vctools\\.*</Source>
                <Source>.*\\public\\sdk\\.*</Source>
                <Source>.*\\microsoft sdks\\.*</Source>
                <Source>.*\\vc\\include\\.*</Source>
              </Exclude>
            </Sources>

            <!-- Match the company name property in the assembly: -->
            <CompanyNames>
              <Exclude>
                <CompanyName>.*microsoft.*</CompanyName>
              </Exclude>
            </CompanyNames>

            <!-- Match the public key token of a signed assembly: -->
            <PublicKeyTokens>
              <!-- Exclude Visual Studio extensions: -->
              <Exclude>
                <PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
                <PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
                <PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
                <PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
                <PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
                <PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
                <PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
              </Exclude>
            </PublicKeyTokens>

            <!-- We recommend you do not change the following values: -->

            <!-- Set this to True to collect coverage information for functions marked with the "SecuritySafeCritical" attribute. Instead of writing directly into a memory location from such functions, code coverage inserts a probe that redirects to another function, which in turns writes into memory. -->
            <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
            <!-- When set to True, collects coverage information from child processes that are launched with low-level ACLs, for example, UWP apps. -->
            <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
            <!-- When set to True, collects coverage information from child processes that are launched by test or production code. -->
            <CollectFromChildProcesses>True</CollectFromChildProcesses>
            <!-- When set to True, restarts the IIS process and collects coverage information from it. -->
            <CollectAspDotNet>False</CollectAspDotNet>
            <!-- When set to True, static native instrumentation will be enabled. -->
            <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation>
            <!-- When set to True, dynamic native instrumentation will be enabled. -->
            <EnableDynamicNativeInstrumentation>True</EnableDynamicNativeInstrumentation>
            <!-- When set to True, instrumented binaries on disk are removed and original files are restored. -->
            <EnableStaticNativeInstrumentationRestore>True</EnableStaticNativeInstrumentationRestore>

          </CodeCoverage>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>
<?xml version="1.0" encoding="utf-8"?>
<!-- File name extension must be .runsettings -->
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
        <Configuration>
          <CodeCoverage>
<!--
Additional paths to search for .pdb (symbol) files. Symbols must be found for modules to be instrumented.
If .pdb files are in the same folder as the .dll or .exe files, they are automatically found. Otherwise, specify them here.
Note that searching for symbols increases code coverage runtime. So keep this small and local.
-->
<!--
            <SymbolSearchPaths>
                   <Path>C:\Users\username\source\repos\ProjectX</Path>
                   <Path>\\mybuildshare\builds\ProjectX</Path>
            </SymbolSearchPaths>
-->

<!--
About include/exclude lists:
Empty "Include" clauses imply all; empty "Exclude" clauses imply none.
Each element in the list is a regular expression (ECMAScript syntax). See /visualstudio/ide/using-regular-expressions-in-visual-studio.
An item must first match at least one entry in the include list to be included.
Included items must then not match any entries in the exclude list to remain included.
-->

            <!-- Match assembly file paths: -->
            <ModulePaths>
              <Include>
                <ModulePath>.*\.dll$</ModulePath>
                <ModulePath>.*\.exe$</ModulePath>
              </Include>
              <Exclude>
                <ModulePath>.*CPPUnitTestFramework.*</ModulePath>
              </Exclude>
              <!-- Specifies additional list of directories where binaries static native instrumentation should be searched. -->
              <IncludeDirectories>
                <Directory Recursive="true">C:\b59fb11c-1611-4562-9a2b-c35719da65d3</Directory>
              </IncludeDirectories>
            </ModulePaths>

            <!-- Match fully qualified names of functions: -->
            <!-- (Use "\." to delimit namespaces in C# or Visual Basic, "::" in C++.)  -->
            <Functions>
              <Exclude>
                <Function>^Fabrikam\.UnitTest\..*</Function>
                <Function>^std::.*</Function>
                <Function>^ATL::.*</Function>
                <Function>.*::__GetTestMethodInfo.*</Function>
                <Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
                <Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
              </Exclude>
            </Functions>

            <!-- Match attributes on any code element: -->
            <Attributes>
              <Exclude>
                <!-- Don't forget "Attribute" at the end of the name -->
                <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>
                <Attribute>^System\.Diagnostics\.DebuggerNonUserCodeAttribute$</Attribute>
                <Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
                <Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
              </Exclude>
            </Attributes>

            <!-- Match the path of the source files in which each method is defined: -->
            <Sources>
              <Exclude>
                <Source>.*\\atlmfc\\.*</Source>
                <Source>.*\\vctools\\.*</Source>
                <Source>.*\\public\\sdk\\.*</Source>
                <Source>.*\\microsoft sdks\\.*</Source>
                <Source>.*\\vc\\include\\.*</Source>
              </Exclude>
            </Sources>

            <!-- Match the company name property in the assembly: -->
            <CompanyNames>
              <Exclude>
                <CompanyName>.*microsoft.*</CompanyName>
              </Exclude>
            </CompanyNames>

            <!-- Match the public key token of a signed assembly: -->
            <PublicKeyTokens>
              <!-- Exclude Visual Studio extensions: -->
              <Exclude>
                <PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
                <PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
                <PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
                <PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
                <PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
                <PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
                <PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
              </Exclude>
            </PublicKeyTokens>

            <!-- We recommend you do not change the following values: -->

            <!-- Set this to True to collect coverage information for functions marked with the "SecuritySafeCritical" attribute. Instead of writing directly into a memory location from such functions, code coverage inserts a probe that redirects to another function, which in turns writes into memory. -->
            <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
            <!-- When set to True, collects coverage information from child processes that are launched with low-level ACLs, for example, UWP apps. -->
            <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
            <!-- When set to True, collects coverage information from child processes that are launched by test or production code. -->
            <CollectFromChildProcesses>True</CollectFromChildProcesses>
            <!-- When set to True, restarts the IIS process and collects coverage information from it. -->
            <CollectAspDotNet>False</CollectAspDotNet>

          </CodeCoverage>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>