Personnaliser l’analyse de la couverture du code
Par défaut, la couverture du code analyse tous les assemblys de la solution chargés pendant les tests unitaires. Nous vous recommandons d’utiliser ce comportement par défaut, car il fonctionne bien la plupart du temps. Pour plus d’informations, consultez Utiliser la couverture du code pour déterminer la quantité de code testé.
Pour exclure le code de test des résultats de couverture du code et inclure uniquement du code d’application, ajoutez l’attribut ExcludeFromCodeCoverageAttribute à votre classe de test.
Pour inclure des assemblys qui ne font pas partie de votre solution, obtenez les fichiers .pdb pour ces assemblys et copiez-les dans le même dossier que les fichiers .dll d’assembly.
Fichier de paramètres d’exécution
Le fichier de paramètres d’exécution est le fichier de configuration utilisé par les outils de test unitaire. Les paramètres de couverture de code avancés sont spécifiés dans un fichier .runsettings.
Pour personnaliser la couverture du code, procédez comme suit :
Ajoutez un fichier de paramètres d’exécution à votre solution. Dans Explorateur de solutions, dans le menu contextuel de votre solution, choisissez Ajouter>nouvel élément, puis sélectionnez fichier XML. Enregistrez le fichier avec un nom tel que CodeCoverage.runsettings.
Si vous ne voyez pas tous les modèles d’élément, choisissez Afficher tous les modèles, puis choisissez le modèle d’élément.
Ajoutez le contenu de l’exemple de fichier à la fin de cet article, puis personnalisez-le en fonction de vos besoins, comme décrit dans les sections suivantes.
Sélectionnez un fichier de paramètres d’exécution.
À compter de Visual Studio 2019 version 16.4, vous pouvez détecter automatiquement un fichier de paramètres d’exécution à la racine du projet. Sinon, dans le menu Tester, choisissez Configurer les paramètres d’exécution, puis choisissez Sélectionnez le fichier d’exécution à l’échelle de la solution. Pour spécifier un fichier de paramètres d’exécution pour exécuter des tests à partir de la ligne de commande, consultez Configurer des tests unitaires.
Quand vous sélectionnez Analyser la couverture du code, les informations de configuration sont lues à partir du fichier de paramètres d’exécution.
Conseil
Les résultats de couverture du code précédents et la coloration du code ne sont pas automatiquement masqués lorsque vous exécutez des tests ou mettez à jour votre code.
Pour désactiver et activer les paramètres personnalisés, désélectionnez ou sélectionnez le fichier dans le menu Test.
Pour sélectionner le fichier de paramètres d’exécution, dans le menu Test, choisissez l’option Sélectionner un fichier de paramètres. Pour spécifier un fichier de paramètres d’exécution pour exécuter des tests à partir de la ligne de commande, consultez Configurer des tests unitaires.
Quand vous sélectionnez Analyser la couverture du code, les informations de configuration sont lues à partir du fichier de paramètres d’exécution.
Conseil
Les résultats de couverture du code précédents et la coloration du code ne sont pas automatiquement masqués lorsque vous exécutez des tests ou mettez à jour votre code.
Pour désactiver et activer les paramètres personnalisés, choisissez Test, Configurer les paramètres d’exécution, puis désélectionnez ou sélectionnez le nom du fichier.
Chemins de recherche de symboles
La couverture du code requiert des fichiers de symboles (fichiers .pdb) pour les assemblys. Pour les assemblys générés par votre solution, les fichiers de symboles sont généralement présents en même temps que les fichiers binaires, et la couverture du code fonctionne automatiquement. Dans certains cas, vous pouvez inclure des assemblies de références dans votre analyse de la couverture de code. Dans ce cas, les fichiers .pdb peuvent ne pas être adjacents aux fichiers binaires, mais vous pouvez spécifier le chemin de recherche de symboles dans le fichier .runsettings.
<SymbolSearchPaths>
<Path>\\mybuildshare\builds\ProjectX</Path>
<!--More paths if required-->
</SymbolSearchPaths>
Remarque
La résolution des symboles peut prendre du temps, surtout quand vous utilisez un emplacement de fichier distant avec de nombreux assemblys. Par conséquent, envisagez de copier fichiers .pdb dans le même emplacement local que les fichiers binaires (.dll et .exe).
Inclure ou exclure des assemblys et des membres
Vous pouvez inclure ou exclure des assemblies ou des types et des membres spécifiques de l'analyse de couverture du code. Si la section Include est vide ou omise, tous les assemblys chargés et qui ont des fichiers PDB associés sont inclus. Si un assembly ou un membre correspond à une clause de la section Exclure, il est exclu de la couverture du code. La section Exclure est prioritaire sur la section Inclure : si un assembly est répertorié à la fois dans Inclure et Exclure, il ne sera pas inclus dans la couverture du code.
Par exemple, le code XML suivant exclut un assembly unique en spécifiant son nom :
<ModulePaths>
<Exclude>
<ModulePath>.*Fabrikam.Math.UnitTest.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Exclude>
</ModulePaths>
L’exemple suivant spécifie que seul un seul assembly doit être inclus dans la couverture du code :
<ModulePaths>
<Include>
<ModulePath>.*Fabrikam.Math.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Include>
</ModulePaths>
Le tableau suivant montre les différentes façons dont les assemblys et les membres peuvent être mis en correspondance pour l’inclusion ou l’exclusion dans la couverture du code.
Élément XML | Ce à quoi il correspond |
---|---|
ModulePath | Correspond aux assemblies spécifiées par le nom de l'assembly ou le chemin du fichier. |
CompanyName | Correspond aux assemblys avec l’attribut Company. |
PublicKeyToken | Correspond aux assemblys signés par le jeton de clé publique. |
Source | Correspond à des éléments avec le chemin du fichier source dans lequel ils sont définis. |
Attribut | Correspond aux éléments qui ont l’attribut spécifié. Spécifiez le nom complet de l’attribut, par exemple <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute> .Si vous excluez l’attribut CompilerGeneratedAttribute, le code qui utilise des fonctionnalités de langage telles que async , await , yield return et les propriétés implémentées automatiquement sont exclues de l’analyse de la couverture du code. Pour exclure le code réellement généré, excluez uniquement l’attribut GeneratedCodeAttribute. |
Fonction | Identifie les procédures, fonctions ou méthodes par nom complet, y compris la liste des arguments. Vous pouvez également faire correspondre une partie du nom à l’aide d’une expression régulière . Exemples: Fabrikam.Math.LocalMath.SquareRoot(double); (C#)Fabrikam::Math::LocalMath::SquareRoot(double) (C++) |
Formats de couverture du code
Par défaut, la couverture du code est collectée et enregistrée dans un fichier .coverage
. Vous pouvez également collecter la couverture à l’aide d’autres formats, notamment Xml et Cobertura. Différents formats peuvent être utiles dans différents éditeurs et pipelines. Vous pouvez l’activer dans runsettings en ajoutant <Format>Cobertura</Format>
ou <Format>Xml</Format>
dans la section de configuration DataCollector de votre fichier runsettings. Ce format peut être affiché dans la fenêtre de résultats de couverture du code dans Visual Studio Enterprise.
Vous pouvez également spécifier différents formats à partir de la ligne de commande en le spécifiant dans le fichier runsettings ou en le spécifiant dans un paramètre. Par exemple, la ligne de commande dotnet utilise dotnet test --collect:"Code Coverage;Format=Cobertura"
. Pour vstest, utilisez vstest.console.exe /collect:"Code Coverage;Format=Cobertura"
. Le paramètre collect remplace le format spécifié dans runsettings.
Instrumentation native statique et dynamique
Dans Visual Studio 2022 version 17.2, nous avons ajouté l’option permettant d’instrumenter le binaire natif de manière statique (sur le disque). Dans les versions précédentes, nous avons pris en charge uniquement l’instrumentation dynamique, ce qui n’était souvent pas en mesure d’instrumenter les méthodes. L’instrumentation native statique est plus stable et elle est recommandée. L’instrumentation native statique nécessite l’activation de l’option de lien /PROFILE pour tous les projets natifs pour lesquels vous avez besoin d’une collection de couverture de code.
Vous pouvez également activer l’instrumentation statique native dans runsettings en ajoutant <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation>
sous <CodeCoverage>
balise. Utilisez cette méthode pour les scénarios de ligne de commande.
Par défaut, l’instrumentation native dynamique est toujours activée. Si l’instrumentation statique et dynamique est activée, Visual Studio tente d’instrumenter votre code C++ de manière statique, mais si cela n’est pas possible (par exemple, lorsque l’option de liaison /PROFILE
n’est pas activée), l’instrumentation dynamique est utilisée. Vous pouvez désactiver entièrement l’instrumentation native dynamique dans runsettings en ajoutant <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>
sous <CodeCoverage>
.
Lorsque l’instrumentation native statique est activée, les fichiers binaires natifs sont instrumentés et remplacés sur le disque avant l’exécution du test. Les fichiers binaires d’origine sont restaurés après l’exécution du test. Vous pouvez désactiver la restauration des fichiers d’origine dans runsettings en ajoutant <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore>
sous la balise <CodeCoverage>
. Cela peut être particulièrement utile dans les scénarios CI.
Lorsque l’instrumentation native statique est activée, Visual Studio recherche et instrumente tous les fichiers binaires natifs dans le répertoire où se trouve le fichier binaire de test. Vous pouvez spécifier des répertoires supplémentaires dans lesquels les fichiers binaires doivent être recherchés. L’exemple suivant spécifie que tous les fichiers binaires natifs de C:\temp
et ses sous-répertoires doivent être instrumentés à l’exception des fichiers se terminant par Fabrikam.Math.dll
.
<ModulePaths>
<IncludeDirectories>
<Directory Recursive="true">C:\temp</Directory>
</IncludeDirectories>
<Exclude>
<ModulePath>.*Fabrikam.Math.dll</ModulePath>
</Exclude>
</ModulePaths>
Expressions régulières
Les nœuds Inclure et Exclure utilisent des expressions régulières, qui ne sont pas identiques à des caractères génériques. Les correspondances ne respectent pas la casse. Voici quelques exemples :
.* correspond à une chaîne de n’importe quel caractère
\. correspond à un point « . »
\( \) correspond aux parenthèses « ( ) »
\\ représente un délimiteur de chemin de fichier « \ »
^ correspond au début de la chaîne
$ correspond à la fin de la chaîne
Le code XML suivant montre comment inclure et exclure des assemblys spécifiques à l’aide d’expressions régulières :
<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>
Le code XML suivant montre comment inclure et exclure des fonctions spécifiques à l’aide d’expressions régulières :
<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>
Avertissement
S’il existe une erreur dans une expression régulière, telle qu’une séquence d’échappement ou une parenthèse sans correspondance, l’analyse de couverture du code ne fonctionne pas.
Pour plus d’informations sur les expressions régulières, consultez Utiliser des expressions régulières dans Visual Studio.
Exemple de fichier .runsettings
Copiez ce code et modifiez-le en fonction de vos besoins.
<?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>