Personalizar a análise de cobertura de código
Por padrão, a análise de cobertura de código abrange todos os conjuntos da solução que são carregados durante os testes de unidade. Recomendamos que você use esse comportamento padrão, porque ele funciona bem na maioria das vezes. Para obter mais informações, consulte Utilizar cobertura de código para determinar quanto código é testado.
Para excluir o código de teste dos resultados da cobertura de código e incluir apenas o código do aplicativo, adicione o atributo ExcludeFromCodeCoverageAttribute à sua classe de teste.
Para incluir assemblies que não fazem parte da solução, obtenha os arquivos .pdb para esses assemblies e copie-os para a mesma pasta que os arquivos de assembly .dll.
Observação
A cobertura de código está disponível somente com o Visual Studio Enterprise. Para cobertura de código .NET, pode-se usar, alternativamente, a ferramenta de linha de comando, dotnet-coverage.
Executar arquivo de configurações
"O ficheiro de definições de execução é utilizado pelas ferramentas de teste de unidade." As definições avançadas de cobertura de código são especificadas num ficheiro de .runsettings.
Para personalizar a cobertura de código, siga estas etapas:
Adicione um arquivo de configurações de execução à sua solução. No Gerenciador de Soluções , no menu de atalho da sua solução, escolha Adicionar>Novo Iteme selecione Arquivo XML. Salve o arquivo com um nome como CodeCoverage.runsettings.
Se não vir todos os modelos de item, escolha Mostrar Todos os Modelose, em seguida, escolha o modelo de item.
Adicione o conteúdo do arquivo de exemplo no final deste artigo e personalize-o de acordo com suas necessidades, conforme descrito nas seções a seguir.
Selecione um arquivo de configurações de execução.
A partir do Visual Studio 2019 versão 16.4, você pode detetar automaticamente um arquivo de configurações de execução na raiz do projeto. Caso contrário, no menu de Testes , escolha Configurar Definições de Execuçãoe, em seguida, escolha Selecionar Ficheiro de Definições de Execução para Toda a Solução. Para especificar um arquivo de configurações de execução para executar testes a partir da linha de comando, consulte Configurar testes de unidade.
Quando selecionas Analisar cobertura de código, as informações de configuração são lidas a partir do arquivo de definições de execução.
Dica
Quaisquer resultados de cobertura de código anteriores e coloração de código não são automaticamente ocultos quando se executam testes ou se atualiza o código.
Para desativar e ativar as configurações personalizadas, desmarque ou selecione o arquivo no menu Test.
Para selecionar o ficheiro de configurações de execução, no menu de teste , escolha Selecionar Ficheiro de Configurações. Para especificar um arquivo de configurações de execução para executar testes a partir da linha de comando, consulte Configurar testes de unidade.
Quando selecionas Analisar cobertura de código, as informações de configuração são lidas a partir do arquivo de definições de execução.
Dica
Quaisquer resultados de cobertura de código anteriores e coloração de código não são automaticamente ocultos quando se executam testes ou se atualiza o código.
Para desativar e ativar as configurações personalizadas, escolha Teste, Configuração da Execuçãoe desmarque ou selecione o nome do ficheiro.
Caminhos de pesquisa de símbolos
A cobertura de código requer arquivos de símbolos (arquivos .pdb) para assemblies. Para conjuntos criados pela sua solução, os ficheiros de símbolo geralmente estão presentes ao lado dos ficheiros binários e a cobertura de código funciona automaticamente. Em alguns casos, talvez você queira incluir assemblies referenciados em sua análise de cobertura de código. Nesses casos, os arquivos de .pdb podem não ser adjacentes aos binários, mas você pode especificar o caminho de pesquisa de símbolos no arquivo de .runsettings.
<SymbolSearchPaths>
<Path>\\mybuildshare\builds\ProjectX</Path>
<!--More paths if required-->
</SymbolSearchPaths>
Observação
A resolução de símbolos pode levar tempo, especialmente ao usar uma localização de ficheiro remota com muitos conjuntos. Portanto, considere copiar os ficheiros .pdb para o mesmo local que os ficheiros binários (.dll e .exe).
Incluir ou excluir assembleias e membros
Você pode incluir ou excluir assemblies ou tipos e membros específicos da análise de cobertura de código. Se a seção Incluir estiver vazia ou omitida, todos os assemblies carregados e com arquivos PDB associados serão incluídos. Se um assembly ou membro corresponder a uma cláusula na secção Excluir, ele é excluído da cobertura de código. A seção Excluir tem precedência sobre a seção Incluir: se um assembly estiver listado em Incluir e Excluir, ele não será incluído na cobertura de código.
Por exemplo, o XML a seguir exclui um único assembly especificando seu nome:
<ModulePaths>
<Exclude>
<ModulePath>.*Fabrikam.Math.UnitTest.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Exclude>
</ModulePaths>
O exemplo a seguir especifica que apenas um único assembly deve ser incluído na cobertura de código:
<ModulePaths>
<Include>
<ModulePath>.*Fabrikam.Math.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Include>
</ModulePaths>
A tabela a seguir mostra as várias maneiras pelas quais assemblies e membros podem ser combinados para inclusão ou exclusão da cobertura de código.
Elemento XML | O que corresponde |
---|---|
ModulePath | Corresponde às assemblagens especificadas pelo nome da assemblagem ou caminho do ficheiro. |
Nome da Empresa | Conjunta conjuntos pelo atributo Company. |
PublicKeyToken | Associa assemblies assinados através do token da chave pública. |
Fonte | Seleciona elementos pelo caminho do ficheiro de origem em que estão definidos. |
Atributo | Corresponde aos elementos que têm o atributo especificado. Especifique o nome completo do atributo, por exemplo, <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute> .Se você excluir o atributo CompilerGeneratedAttribute, o código que usa recursos de linguagem como async , await , yield return e propriedades auto-implementadas será excluído da análise de cobertura de código. Para excluir o código verdadeiramente gerado, exclua apenas o atributo GeneratedCodeAttribute. |
Função | Corresponde procedimentos, funções ou métodos por nome totalmente qualificado, incluindo a lista de parâmetros. Você também pode combinar parte do nome usando uma expressão regular . Exemplos: Fabrikam.Math.LocalMath.SquareRoot(double); (C#)Fabrikam::Math::LocalMath::SquareRoot(double) (C++) |
Formatos de cobertura de código
Por padrão, a cobertura de código é coletada e salva em um arquivo .coverage
. Você também pode coletar cobertura usando outros formatos, incluindo Xml e Cobertura. Diferentes formatos podem ser úteis em diferentes editores e pipelines. Você pode habilitar isso em runsettings adicionando <Format>Cobertura</Format>
ou <Format>Xml</Format>
na seção de configuração DataCollector em seu arquivo runsettings. Esse formato pode ser exibido na janela de resultados de cobertura de código no Visual Studio Enterprise.
Você também pode especificar formatos diferentes da linha de comando especificando-os no arquivo runsettings ou especificando-os em um parâmetro. Por exemplo, o comando dotnet a partir da linha de comandos usa dotnet test --collect:"Code Coverage;Format=Cobertura"
. Para a utilização de vstest, use vstest.console.exe /collect:"Code Coverage;Format=Cobertura"
. O parâmetro collect substituirá o formato especificado em runsettings.
Instrumentação nativa estática e dinâmica
Na versão 17.2 do Visual Studio 2022, adicionámos a opção de instrumentar o binário nativo de forma estática (no disco). Nas versões anteriores, suportamos apenas instrumentação dinâmica, que muitas vezes não era capaz de instrumentar métodos. A instrumentação nativa estática é mais estável e é recomendada. A instrumentação nativa estática requer a ativação da opção de link de /PROFILE para todos os projetos nativos para os quais você precisa coletar cobertura de código.
Você também pode habilitar a instrumentação estática nativa ao adicionar <EnableStaticNativeInstrumentation>True</EnableStaticNativeInstrumentation>
sob a tag <CodeCoverage>
em runsettings. Use esse método para cenários de linha de comando.
Por padrão, a instrumentação nativa dinâmica está sempre ativada. Se a instrumentação estática e dinâmica estiver habilitada, o Visual Studio tentará instrumentar seu código C++ estaticamente, mas se isso não for possível (por exemplo, quando a opção de link /PROFILE
não estiver habilitada), a instrumentação dinâmica será usada. Você pode desativar totalmente a instrumentação nativa dinâmica nas definições de execução adicionando <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>
em <CodeCoverage>
.
Quando a instrumentação nativa estática estiver habilitada, os binários nativos serão instrumentados e substituídos no disco antes da execução do teste. Os binários originais serão restaurados após a execução do teste. Você pode desativar a restauração de arquivos originais em runsettings adicionando <EnableStaticNativeInstrumentationRestore>False</EnableStaticNativeInstrumentationRestore>
sob a tag <CodeCoverage>
. Isso pode ser especialmente útil em cenários de IC.
Quando a instrumentação nativa estática está habilitada, o Visual Studio pesquisará e instrumentará todos os binários nativos no diretório onde o binário de teste está localizado. Você pode especificar diretórios adicionais onde os binários devem ser pesquisados. O exemplo a seguir especifica que todos os binários nativos do C:\temp
e seus subdiretórios devem ser instrumentados, exceto arquivos que terminam com Fabrikam.Math.dll
.
<ModulePaths>
<IncludeDirectories>
<Directory Recursive="true">C:\temp</Directory>
</IncludeDirectories>
<Exclude>
<ModulePath>.*Fabrikam.Math.dll</ModulePath>
</Exclude>
</ModulePaths>
Expressões regulares
Os nós de inclusão e exclusão usam expressões regulares, que não são iguais a curingas. Todas as correspondências são insensíveis a maiúsculas e minúsculas. Alguns exemplos são:
.* corresponde a uma cadeia de caracteres
\. corresponde a um ponto "."
\( \) corresponde aos parênteses "( )"
\\ corresponde a um delimitador de caminho de arquivo "\"
^ corresponde ao início da cadeia de caracteres
$ corresponde ao final da cadeia de caracteres
O XML a seguir mostra como incluir e excluir assemblies específicos usando expressões regulares:
<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>
O XML a seguir mostra como incluir e excluir funções específicas usando expressões regulares:
<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>
Advertência
Se houver um erro em uma expressão regular, como um parêntese sem escape ou incomparável, a análise de cobertura de código não será executada.
Para obter mais informações sobre expressões regulares, consulte Usar expressões regulares no Visual Studio.
Exemplo de arquivo .runsettings
Copie este código e edite-o de acordo com as suas necessidades.
<?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>