Sdílet prostřednictvím


Přizpůsobte analýzu pokrytí kódu

Pokrytí kódu ve výchozím nastavení analyzuje všechna sestavení řešení načtená během jednotkových testů. 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 do testovací třídy atribut ExcludeFromCodeCoverageAttribute.

Pokud chcete 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í.

Poznámka

Pokrytí kódu je k dispozici pouze se sadou Visual Studio Enterprise. Pro pokrytí kódu .NET můžete alternativně použít nástroj příkazového řádku, dotnet-coverage.

Spustit soubor nastavení

Soubor nastavení běhu je konfigurační soubor používaný nástroji pro jednotkové testování. Pokročilá nastavení pokrytí kódu jsou zadána 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íku řešenív místní nabídce vaší řešení zvolte Přidat>Nová Položkaa vyberte XML soubor. Uložte soubor s názvem, například CodeCoverage.runsettings.

    Pokud nevidíte všechny šablony položek, zvolte Zobrazit všechny šablonya 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í.

    Od verze Visual Studio 2019 16.4 můžete automaticky detekovat soubor nastavení spuštění v hlavním adresáři projektu. V opačném případě v nabídce Test zvolte Konfigurovat nastavení spuštěnía poté zvolte Vybrat soubor runsettings pro celé ř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 Konfigurace testů jednotek.

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

    Spropitné

    Předchozí výsledky pokrytí kódu a zvýraznění kódu se při spuštění testů nebo aktualizaci kódu automaticky neskrývají.

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

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

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

    Spropitné

    Předchozí výsledky pokrytí kódu a zvýraznění kódu se při spuštění testů nebo aktualizaci kódu automaticky neskrývají.

    Pokud chcete vlastní nastavení vypnout a zapnout, zvolte Test, Nastavit spuštěnía vyberte či zrušte výběr názvu souboru.

Cesty hledání symbolů

Pokrytí kódu vyžaduje soubory symbolů (.pdb soubory) 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 část Zahrnout prázdná či vynechána, pak jsou zahrnuta všechna sestavení, která byla načtena a mají přidružené PDB soubory. 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í uvedeno v Zahrnout i Vyloučit, nebude zahrnuta do 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 zahrnout či vyloučit z pokrytí kódu.

XML element S čím se to shoduje
ModulePath Odpovídá sestavením určeným názvem sestavení nebo cestou k souboru.
Název společnosti Porovnává sestavení podle atributu Company.
PublicKeyToken Porovnává podepsaná sestavení pomocí tokenu veřejného klíče.
Zdroj 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 vyloučíte atribut CompilerGeneratedAttribute, kód, který používá jazykové funkce, jako jsou async, await, yield returna automaticky implementované vlastnosti, se z analýzy pokrytí kódu vyloučil. Chcete-li vyloučit skutečně vygenerovaný kód, vylučte pouze atribut GeneratedCodeAttribute.
Funkce Odpovídá procedurám, funkcím nebo metodám podle plně kvalifikovaného názvu, včetně seznamu parametrů. Část názvu můžete najít také 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 pokrytí kódu shromažďuje a ukládá do souboru .coverage. 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. Můžete to povolit v runsettings přidáním <Format>Cobertura</Format> nebo <Format>Xml</Format> v části konfigurace 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žijte 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 /PROFILE připojení pro všechny nativní projekty, pro které potřebujete sběr dat o pokrytí kódu.

Nativní statickou instrumentaci můžete také povolit v runsettings přidáním <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation> pod značku <CodeCoverage>. 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 povolena statická i dynamická instrumentace, Visual Studio se pokusí instrumentovat váš kód C++ staticky, ale pokud to není možné (například když není povolena volba propojení /PROFILE), bude použita dynamická instrumentace. Dynamické nativní instrumentace můžete v souboru runsettings plně zakázat přidáním <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation> do <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 runsettings můžete zakázat přidáním <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore> pod značku <CodeCoverage>. 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 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é znaky. Všechny shody nerozlišují malá a velká písmena. Mezi příklady patří:

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

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

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

  • \\ 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>

Varování

Pokud v regulárním výrazu dojde k chybě, například neescapovanou nebo neuzavřenou závorku, analýza pokrytí kódu se nespustí.

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

Ukázkový soubor .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>
            <Format>coverage</Format>
<!--
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>