Udostępnij za pośrednictwem


Dostosowywanie analizy pokrycia kodu

Domyślnie pokrycie kodu analizuje wszystkie zestawy składowe rozwiązania, które są ładowane podczas testów jednostkowych. Zalecamy użycie tego domyślnego zachowania, ponieważ działa ono przez większość czasu. Aby uzyskać więcej informacji, zobacz Używanie pokrycia kodu w celu określenia, ile kodu jest testowane.

Aby wykluczyć kod testowy z wyników pokrycia kodu i dołączyć tylko kod aplikacji, dodaj atrybut ExcludeFromCodeCoverageAttribute do klasy testowej.

Aby dołączyć zestawy, które nie są częścią rozwiązania, uzyskaj pliki .pdb dla tych zestawów i skopiuj je do tego samego folderu co pliki .dll zestawu.

Uruchom plik ustawień

Plik ustawień uruchamiania jest plikiem konfiguracji używanym przez narzędzia testowania jednostkowego. Zaawansowane ustawienia pokrycia kodu są określone w pliku .runsettings.

Aby dostosować krycie kodu, wykonaj następujące kroki:

  1. Dodaj plik ustawień uruchamiania do rozwiązania. W Eksploratorze Rozwiązań , w menu skrótów rozwiązania wybierz Dodaj>Nowy element, a następnie wybierz Plik XML . Zapisz plik pod nazwą, taką jak CodeCoverage.runsettings.

    Jeśli nie widzisz wszystkich szablonów elementów, wybierz pozycję Pokaż wszystkie szablony, a następnie wybierz szablon elementu.

  2. Dodaj zawartość z przykładowego pliku na końcu tego artykułu, a następnie dostosuj ją do swoich potrzeb zgodnie z opisem w poniższych sekcjach.

  3. Wybierz plik ustawień uruchamiania.

    Od wersji Visual Studio 2019 16.4 możesz automatycznie wykrywać plik ustawień uruchamiania w katalogu głównym projektu. W przeciwnym razie w menu testowym wybierz Skonfiguruj ustawienia uruchamiania, a następnie wybierz Wybierz plik ustawień dla całego rozwiązania. Aby określić plik ustawień uruchamiania na potrzeby uruchamiania testów z poziomu wiersza polecenia, zobacz Konfigurowanie testów jednostkowych.

    Po wybraniu Analizuj pokrycie kodu, informacje o konfiguracji są odczytywane z pliku ustawień wykonywania.

    Napiwek

    Wszystkie poprzednie wyniki pokrycia kodu i kolorowanie kodu nie są automatycznie ukryte podczas uruchamiania testów ani aktualizowania kodu.

    Aby włączać i wyłączać ustawienia niestandardowe, zaznacz lub odznacz plik w menu Test.

    Aby wybrać plik ustawień uruchamiania, w menu testu wybierz pozycję Wybierz plik ustawień. Aby określić plik ustawień uruchamiania na potrzeby uruchamiania testów z poziomu wiersza polecenia, zobacz Konfigurowanie testów jednostkowych.

    Gdy wybierzesz Analizuj Pokrycie Kodu, to informacje o konfiguracji są odczytywane z pliku ustawień uruchamiania.

    Napiwek

    Jakiekolwiek poprzednie wyniki pokrycia kodu i kolorowanie kodu nie zostają automatycznie ukryte podczas uruchamiania testów lub aktualizowania kodu.

    Aby przełączać ustawienia niestandardowe, wybierz Test, Konfiguracja ustawień uruchamianiai odznacz lub zaznacz nazwę pliku.

Ścieżki wyszukiwania symboli

Pokrycie kodu wymaga plików symboli (pliki.pdb) dla zestawów. W przypadku zestawów utworzonych przez rozwiązanie pliki symboli są zwykle obecne wraz z plikami binarnymi, a pokrycie kodu działa automatycznie. W niektórych przypadkach możesz chcieć uwzględnić w analizie pokrycia kodu zestawy referencyjne. W takich przypadkach pliki .pdb mogą nie sąsiadować z plikami binarnymi, ale można określić ścieżkę wyszukiwania symboli w pliku .runsettings.

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

Notatka

Rozpoznawanie symboli może zająć trochę czasu, zwłaszcza w przypadku korzystania ze zdalnej lokalizacji pliku z wieloma zestawami. W związku z tym należy rozważyć skopiowanie plików .pdb do tej samej lokalizacji lokalnej co pliki binarne (.dll i .exe).

Dołączanie lub wykluczanie zestawów i członków

Możesz dołączyć lub wykluczyć zestawy lub określone typy i elementy członkowskie z analizy pokrycia kodu. Jeśli sekcja Uwzględnij jest pusta lub pominięta, dołączone zostaną wszystkie zespoły, które są ładowane i mają skojarzone pliki PDB. Jeśli zestaw lub składowa pasuje do klauzuli w sekcji Wyklucz, zostanie ona wykluczona z pokrycia kodu. Sekcja Wyklucz ma pierwszeństwo przed sekcją Uwzględnij: jeśli zestaw jest wymieniony zarówno w Uwzględnij, jak i Wyklucz, to nie zostanie uwzględniony w pokryciu kodu.

Na przykład następujący kod XML wyklucza pojedynczy zestaw, określając jego nazwę:

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

W poniższym przykładzie określono, że tylko jeden zestaw powinien być uwzględniony w pokryciu kodu:

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

W poniższej tabeli przedstawiono różne sposoby dopasowywania zespołów i członków do włączenia lub wykluczenia z pokrycia kodu.

Element XML To, co pasuje
ModulePath Pasuje do zestawów określonych przez nazwę zestawu lub ścieżkę pliku.
Nazwa firmy Dopasuje zestawy według atrybutu firmy.
PublicKeyToken Pasuje do podpisanych zestawów za pomocą tokenu klucza publicznego.
Źródło Dopasuje elementy według nazwy ścieżki pliku źródłowego, w którym są zdefiniowane.
Atrybut Dopasuje elementy, które mają określony atrybut. Określ pełną nazwę atrybutu, na przykład <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>.

Jeśli wykluczysz atrybut CompilerGeneratedAttribute, kod korzystający z funkcji językowych, takich jak async, await, yield returni automatycznie zaimplementowane właściwości zostaną wykluczone z analizy pokrycia kodu. Aby wykluczyć prawdziwie wygenerowany kod, wyklucz tylko atrybut GeneratedCodeAttribute.
Funkcja Dopasowuje procedury, funkcje lub metody po w pełni kwalifikowanej nazwie, w tym listy parametrów. Możesz również dopasować część nazwy przy użyciu wyrażenia regularnego .

Przykłady:

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

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

Formaty pokrycia kodu

Domyślnie pokrycie kodu jest rejestrowane i zapisywane w pliku .coverage. Można również zbierać dane pokrycia przy użyciu innych formatów, takich jak xml i Cobertura. Różne formaty mogą być przydatne w różnych edytorach i potokach. Można to włączyć w runsettings, dodając <Format>Cobertura</Format> lub <Format>Xml</Format> w sekcji konfiguracji DataCollector w pliku runsettings. Ten format można wyświetlić w oknie wyników pokrycia kodu w programie Visual Studio Enterprise.

Można również określić różne formaty z wiersza polecenia, określając go w pliku runsettings lub określając go w parametrze. Na przykład wiersz polecenia dotnet używa dotnet test --collect:"Code Coverage;Format=Cobertura". W przypadku programu vstest użyj vstest.console.exe /collect:"Code Coverage;Format=Cobertura". Parametr collect zastąpi format określony w parametrze runsettings.

Instrumentacja statyczna i dynamiczna natywna

W programie Visual Studio 2022 w wersji 17.2 dodaliśmy opcję statycznej instrumentacji natywnych plików binarnych (na dysku). W poprzednich wersjach obsługiwana była tylko instrumentacja dynamiczna, która często nie była w stanie instrumentować metod. Instrumentacja statyczna natywna jest bardziej stabilna i jest zalecana. Instrumentacja statyczna rodzima wymaga włączenia opcji linku /PROFILE dla wszystkich projektów natywnych, dla których potrzebujesz zebrania pokrycia kodowego.

Możesz również włączyć natywną instrumentację statyczną w ustawieniach uruchamiania, dodając <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation> pod tagiem <CodeCoverage>. Użyj tej metody w scenariuszach wiersza polecenia.

Domyślnie instrumentacja dynamiczna natywna jest zawsze włączona. Jeśli zarówno instrumentacja statyczna, jak i dynamiczna jest włączona, program Visual Studio próbuje instrumentować kod C++ statycznie, ale jeśli nie jest to możliwe (na przykład gdy opcja linku /PROFILE nie jest włączona), zostanie użyta instrumentacja dynamiczna. Dynamiczną instrumentację natywną można w pełni wyłączyć za pomocą ustawień runsettings, dodając <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation> pod <CodeCoverage>.

Po włączeniu instrumentacji statycznej natywnej natywne pliki binarne będą instrumentowane i zastępowane na dysku przed wykonaniem testu. Oryginalne pliki binarne zostaną przywrócone po wykonaniu testu. Przywracanie oryginalnych plików w ramach ustawień uruchamiania można wyłączyć, dodając <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore> w tagu <CodeCoverage>. Może to być szczególnie przydatne w scenariuszach ciągłej integracji.

Po włączeniu instrumentacji statycznej natywnej program Visual Studio będzie wyszukiwać i instrumentować wszystkie natywne pliki binarne w katalogu, w którym znajduje się testowy plik binarny. Możesz określić dodatkowe katalogi, w których mają być przeszukiwane pliki binarne. Poniższy przykład określa, że wszystkie natywne pliki binarne z C:\temp i jego podkatalogów powinny być instrumentowane z wyjątkiem plików kończących się Fabrikam.Math.dll.

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

Wyrażenia regularne

Węzły dołączania i wykluczania używają wyrażeń regularnych, które nie są takie same jak symbole wieloznaczne. Wszystkie dopasowania są bez uwzględniania wielkości liter. Oto kilka przykładów:

  • .* pasuje do ciągu dowolnych znaków

  • \. dopasowuje się do kropki "."

  • \( \) dopasowuje nawiasy "( )"

  • \\ pasuje do ogranicznika ścieżki pliku "\"

  • ^ pasuje do początku ciągu

  • $ pasuje do końca ciągu tekstowego

Poniższy kod XML pokazuje, jak dołączać i wykluczać określone zestawy przy użyciu wyrażeń regularnych:

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

Poniższy kod XML przedstawia sposób dołączania i wykluczania określonych funkcji przy użyciu wyrażeń regularnych:

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

Ostrzeżenie

Jeśli wystąpi błąd w wyrażeniu regularnym, takim jak niewyrównane lub niedopasowane nawiasy, analiza pokrycia kodu nie zostanie uruchomiona.

Aby uzyskać więcej informacji na temat wyrażeń regularnych, zobacz Używanie wyrażeń regularnych w programie Visual Studio.

Przykładowy plik .runsettings

Skopiuj ten kod i zmodyfikuj go zgodnie z potrzebami.

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