Freigeben über


Anpassen der Code Coverage-Analyse

Standardmäßig werden bei der Code Coverage-Analyse alle Projektmappenassemblys analysiert, die während der Komponententests geladen werden. Es wird empfohlen, dieses Standardverhalten beizubehalten, da es meist gut funktioniert. Weitere Informationen finden Sie unter Bestimmen des Umfangs des zu testenden Codes mithilfe von Code Coverage.

Fügen Sie das Attribut ExcludeFromCodeCoverageAttribute zu Ihrer Testklasse hinzu, um Testcode aus den Code Coverage-Ergebnissen auszuschließen und nur Anwendungscode einzuschließen.

Rufen Sie die PDB-Dateien für diese Assemblys ab, und kopieren Sie sie in den gleichen Ordner wie die DLL-Assemblydateien, um Assemblys einzuschließen, die nicht Teil Ihrer Projektmappe sind.

Testlaufeinstellungsdatei

Die Testlaufeinstellungsdatei ist die Konfigurationsdatei, die von den Tools für Komponententests verwendet wird. Erweiterte Code Coverage-Einstellungen werden in einer RUNSETTINGS-Datei angegeben.

Führen Sie die folgenden Schritte aus, um Code Coverage anzupassen:

  1. Fügen Sie eine Testlaufeinstellungsdatei zu Ihrer Projektmappe hinzu. Wählen sie im Projektmappen-Explorer im Kontextmenü Ihrer Projektmappe die Option Hinzufügen>Neues Element und XML-Datei aus. Speichern Sie die Datei mit einem Namen wie z.B. CodeCoverage.runsettings.

    Wenn nicht alle Elementvorlagen angezeigt werden, wählen Sie Alle Vorlagen anzeigen und dann die Elementvorlage aus.

  2. Fügen Sie den Inhalt der Beispieldatei am Ende dieses Artikels hinzu, und passen Sie diesen anschließend wie in den folgenden Abschnitten beschrieben an Ihre Anforderungen an.

  3. Auswählen einer Laufzeiteinstellungsdatei.

    Ab Visual Studio 2019 Version 16.4 können Sie eine Ausführungseinstellungsdatei automatisch im Projektstamm ermitteln. Wählen Sie andernfalls im Menü Test die Option Ausführungseinstellungen konfigurieren und dann Projektmappenweite Ausführungseinstellungsdatei auswählen aus. Informationen zur Angabe einer Testlaufeinstellungsdatei für die Ausführung von Tests über die Befehlszeile finden Sie unter Konfigurieren von Komponententests.

    Wenn Sie Code Coverage analysieren auswählen, werden die Konfigurationsinformationen aus der Testlaufeinstellungsdatei gelesen.

    Tipp

    Alle vorherigen Code Coverage-Ergebnisse und Codefarben werden nicht automatisch ausgeblendet, wenn Sie Tests ausführen oder Ihren Code aktualisieren.

    Deaktivieren oder aktivieren Sie die Datei im Menü Test , um die benutzerdefinierten Einstellungen ein- und auszuschalten.

    Klicken Sie im Menü Test auf die Option Datei für Testeinstellungen auswählen, um die Testeinstellungsdatei auszuwählen. Informationen zur Angabe einer Testlaufeinstellungsdatei für die Ausführung von Tests über die Befehlszeile finden Sie unter Konfigurieren von Komponententests.

    Wenn Sie Code Coverage analysieren auswählen, werden die Konfigurationsinformationen aus der Testlaufeinstellungsdatei gelesen.

    Tipp

    Alle vorherigen Code Coverage-Ergebnisse und Codefarben werden nicht automatisch ausgeblendet, wenn Sie Tests ausführen oder Ihren Code aktualisieren.

    Um die benutzerdefinierten Einstellungen zu deaktivieren und zu aktivieren, wählen Sie Test, Ausführungseinstellungen konfigurieren aus, und deaktivieren oder aktivieren Sie den Dateinamen.

Symbolsuchpfade

Für die Code Coverage sind Symboldateien (PDB-Dateien) für Assemblys erforderlich. Für über die Projektmappe erstellte Assemblys werden Symboldateien meistens neben den Binärdateien bereitgestellt, und die Code Coverage funktioniert automatisch. In einigen Fällen sollten Sie Assemblys, auf die verwiesen wird, in die Code Coverage-Analyse einschließen. In solchen Fällen befinden sich die PDB-Dateien möglicherweise nicht neben den Binärdateien. Sie können jedoch den Symbolsuchpfad in der RUNSETTINGS-Datei angeben.

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

Hinweis

Die Symbolauflösung kann zeitaufwendig sein, insbesondere wenn sie einen Remotedateispeicherort mit zahlreichen Assemblys verwendet. Daher sollten Sie in Erwägung ziehen, die PDB-Dateien in denselben lokalen Speicherort zu kopieren wie die Binärdateien (DLL und EXE).

Einschließen oder Ausschließen von Assemblys und Membern

Sie können Assemblys oder spezifische Typen und Member für die Code Coverage-Analyse einschließen oder ausschließen. Wenn der Abschnitt Include (Einschließen) leer ist oder ausgelassen wird, werden alle geladenen Assemblys und deren zugehörigen PDB-Dateien eingeschlossen. Wenn eine Assembly oder ein Member mit einer Klausel im Abschnitt Exclude (Ausschließen) übereinstimmt, wird sie bzw. er von der Code Coverage-Analyse ausgeschlossen. Der Abschnitt Exclude (Ausschließen) hat Vorrang vor dem Abschnitt Include (Einschließen): Wenn eine Assembly sowohl in Include als auch in Exclude aufgeführt wird, wird sie nicht in die Code Coverage-Analyse eingeschlossen.

Mit dem folgenden XML-Code wird eine einzelne Assembly beispielsweise ausgeschlossen, indem ihr Name angegeben wird:

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

Im folgenden Beispiel wird festgelegt, dass nur eine einzelne Assembly in Code Coverage enthalten werden soll:

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

In der folgenden Tabelle werden die verschiedenen Methoden aufgeführt, mit denen Assemblys und Member zum Einschließen oder Ausschließen aus Code Coverage identifiziert werden können.

XML-Element Gesuchte Übereinstimmung
ModulePath Gleicht Assemblys anhand des Assemblynamens oder Dateipfads ab.
CompanyName Gleicht Assemblys anhand des Attributs Company ab.
PublicKeyToken Gleicht signierte Assemblys nach dem öffentlichen Schlüsseltoken ab.
Quelle Gleicht Elemente anhand des Pfadnamens der Quelldatei ab, in der sie definiert sind.
Attribut Entspricht Elementen, die das festgelegte Attribut aufweisen. Geben Sie den vollständigen Namen des Attributs an (beispielsweise <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>).

Wenn Sie das Attribut CompilerGeneratedAttribute ausschließen, werden Code, der Sprachfunktionen wie async, await und yield return verwendet, und automatisch implementierte Eigenschaften von der Code Coverage-Analyse ausgeschlossen. Wenn Sie tatsächlich generierten Code ausschließen möchten, schließen Sie nur das Attribut GeneratedCodeAttribute aus.
Funktion Gleicht Prozeduren, Funktionen oder Methoden nach dem vollqualifizierten Namen, einschließlich der Parameterliste, ab. Mithilfe eines regulären Ausdrucks können Sie auch nach einer Übereinstimmung mit einem Teil des Namens suchen.

Beispiele:

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

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

Code Coverage-Formate

Standardmäßig wird die Code Coverage gesammelt und in einer .coverage-Datei gespeichert. Sie können die Coverage auch mit anderen Formaten erfassen, einschließlich XML und Cobertura. Unterschiedliche Formate können in verschiedenen Editoren und Pipelines nützlich sein. Sie können dies in RunSettings aktivieren, indem Sie <Format>Cobertura</Format> oder <Format>Xml</Format> im Abschnitt für die DataCollector-Konfiguration in Ihrer RUNSETTINGS-Datei hinzufügen. Dieses Format kann im Code Coverage-Ergebnisfenster in Visual Studio Enterprise angezeigt werden.

Sie können auch verschiedene Formate über die Befehlszeile angeben, indem Sie sie entweder in der RUNSETTINGS-Datei oder in einem Parameter angeben. Die dotnet-Befehlszeile verwendet beispielsweise dotnet test --collect:"Code Coverage;Format=Cobertura". Verwenden Sie für vstest vstest.console.exe /collect:"Code Coverage;Format=Cobertura". Der collect-Parameter überschreibt das in runsettings angegebene Format.

Statische und dynamische native Instrumentierung

In Visual Studio 2022 Version 17.2 wurde die Option zum statischen (auf Datenträger) Instrumentieren nativer Binärdateien hinzugefügt. In früheren Versionen unterstützten wir nur dynamische Instrumentierung, die oft nicht in der Lage war, Methoden zu instrumentieren. Statische native Instrumentierung ist stabiler und wird empfohlen. Statische native Instrumentierung erfordert die Aktivierung der Linkoption /PROFILE für alle nativen Projekte, für die Sie Code Coveragesammlung benötigen.

Sie können die native statische Instrumentierung aktivieren, indem Sie die Vorschaufunktion Native statische Instrumentierung der Code Coverage unter Extras > Optionen > Umgebung > Vorschaufunktionen aktivieren.

Sie können auch native statische Instrumentierung in Runsettings aktivieren, indem Sie <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation> unter dem <CodeCoverage>-Tag hinzufügen. Verwenden Sie diese Methode für Befehlszeilenszenarien.

Standardmäßig ist immer die dynamische native Instrumentierung aktiviert. Wenn statische und dynamische Instrumentierung aktiviert ist, versucht Visual Studio, Ihren C++-Code statisch zu instrumentieren, aber wenn dies nicht möglich ist (z. B. wenn die /PROFILE-Linkoption nicht aktiviert ist), wird dynamische Instrumentierung verwendet. Sie können dynamische native Instrumentierung in Runsettings vollständig deaktivieren, indem Sie unter <CodeCoverage><EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>hinzufügen.

Wenn die statische native Instrumentierung aktiviert ist, werden native Binärdateien vor der Testausführung instrumentiert und auf dem Datenträger ersetzt. Ursprüngliche Binärdateien werden nach der Testausführung wiederhergestellt. Sie können das Wiederherstellen von ursprünglichen Dateien in Runsettings deaktivieren, indem Sie <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore> unter dem <CodeCoverage>-Tag hinzufügen. Dies kann in CI-Szenarien besonders nützlich sein.

Wenn die statische native Instrumentierung aktiviert ist, sucht Visual Studio alle nativen Binärdateien im Verzeichnis, in dem sich die Test-Binärdatei befindet. Sie können zusätzliche Verzeichnisse angeben, in denen nach Binärdateien gesucht werden soll. Im folgenden Beispiel wird angegeben, dass alle nativen Binärdateien aus C:\temp und ihre Unterverzeichnisse mit Ausnahme von Dateien, die mit Fabrikam.Math.dll enden, instrumentiert werden sollten.

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

Reguläre Ausdrücke

Include- und exclude-Knoten verwenden reguläre Ausdrücke, die nicht mit Platzhaltern identisch sind. Bei allen Entsprechungen wird die Groß-/Kleinschreibung nicht beachtet. Beispiele:

  • .* entspricht einer Zeichenfolge beliebiger Zeichen

  • \. entspricht einem Punkt „.“

  • \( \) entspricht Klammern „( )“

  • \\ entspricht dem Dateipfadtrennzeichen „\“

  • ^ entspricht dem Anfang der Zeichenfolge

  • $ entspricht dem Ende der Zeichenfolge

Im folgenden XML-Code wird veranschaulicht, wie Sie spezifische Assemblys mithilfe von regulären Ausdrücken einschließen oder ausschließen:

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

Im folgenden XML-Code wird veranschaulicht, wie Sie spezifische Funktionen mithilfe von regulären Ausdrücken einschließen oder ausschließen:

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

Warnung

Wenn ein Fehler in einem regulären Ausdruck auftritt, z.B. eine Klammer ohne Escapezeichen oder Übereinstimmung, wird die Code Coverage-Analyse nicht ausgeführt.

Weitere Informationen zu regulären Ausdrücken finden Sie unter Verwenden von regulären Ausdrücken in Visual Studio.

Beispiel für eine RUNSETTINGS-Datei

Kopieren Sie diesen Code, und passen Sie ihn Ihren Anforderungen entsprechend an.

<?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>