dotnet cli - specified .runsettings file not used in code coverage run

时间:2019-01-18 18:57:35

标签: c# .net testing code-coverage cobertura

I have a solution containing two dotnet core 2.1 projects (c#).

  1. The first is a console application

  2. The seconds is a test project with unit tests

I generate code coverage stats about project 1 when executing tests in project 2 using this command:

dotnet test C:\tempDir\SampleApp\Tests\SampleApp.Tests.csproj 
/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura 
/p:CoverletOutput=C:\tempDir\Coverage\coverage 
/p:settings=CodeCoverage.runsettings --filter Category=Unit --logger trx 
--results-directory C:\tempDir\output

You can see here I specify CodeCoverage.runsettings as the settings parameter - /p:settings=CodeCoverage.runsettings. In my run settings file, I've asked that Program.cs and Startup.cs are excluded from coverage, but they are still included in the output coverage.cobertura.xml file.

Extract from output report below:

<classes>
    <class name="SampleApp.Startup" filename="SampleApp\Startup.cs" line-rate="1" branch-rate="0" complexity="2">
      <methods>
        <method name="ConfigureAppConfiguration" signature="(Microsoft.Extensions.Configuration.IConfigurationBuilder)" line-rate="1" branch-rate="0">
          <lines>
            <line number="18" hits="1" branch="False" />
            <line number="19" hits="1" branch="False" />
            <line number="20" hits="1" branch="False" />
          </lines>
        </method>
        <method name="ConfigureLogging" signature="(Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Logging.ILoggingBuilder)" line-rate="1" branch-rate="0">
          <lines>
            <line number="23" hits="1" branch="False" />
            <line number="24" hits="1" branch="False" />
            <line number="25" hits="1" branch="False" />
            <line number="26" hits="1" branch="False" />
            <line number="27" hits="1" branch="False" />
          </lines>
        </method>
      </methods>
      <lines>
        <line number="18" hits="1" branch="False" />
        <line number="19" hits="1" branch="False" />
        <line number="20" hits="1" branch="False" />
        <line number="23" hits="1" branch="False" />
        <line number="24" hits="1" branch="False" />
        <line number="25" hits="1" branch="False" />
        <line number="26" hits="1" branch="False" />
        <line number="27" hits="1" branch="False" />
      </lines>
    </class>
</classes>

I'm wondering what I've done wrong in my runsettings file? (contents of file below)

<?xml version="1.0" encoding="utf-8"?>

<RunSettings>
    <!-- Configurations for data collectors -->
    <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>

                        <ModulePaths>
                            <Include>
                                <ModulePath>.*dll$</ModulePath>
                            </Include>
                            <Exclude>
                                <ModulePath>.*microsoft.*</ModulePath>
                                <ModulePath>.*moq.*</ModulePath>
                                <ModulePath>.*polly.*</ModulePath>
                                <ModulePath>.*fluentassertions.*</ModulePath>
                                <ModulePath>.*newtonsoft.*</ModulePath>
                                <ModulePath>.*SampleApp.Tests.*</ModulePath>
                                <ModulePath>.*\\[^\\]*DocumentManagement[^\\]*\.dll</ModulePath>
                            </Exclude>
                        </ModulePaths>

                        <Functions>
                            <Exclude>
                                <Function>.*\.Program\..*</Function>
                                <Function>.*\.Startup\..*</Function>
                                <Function>.*\.SomeOtherClass\..*</Function>
                            </Exclude>
                        </Functions>

                        <Attributes>
                            <Exclude>
                                <Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>
                                <Attribute>^System\.Diagnostics\.DebuggerNonUserCodeAttribute$</Attribute>
                                <Attribute>^System\.Runtime\.CompilerServices.CompilerGeneratedAttribute$</Attribute>
                                <Attribute>^System\.CodeDom\.Compiler.GeneratedCodeAttribute$</Attribute>
                                <Attribute>^System\.Diagnostics\.CodeAnalysis.ExcludeFromCodeCoverageAttribute$</Attribute>
                            </Exclude>
                        </Attributes>

                        <!-- We recommend you do not change the following values: -->
                        <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
                        <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
                        <CollectFromChildProcesses>True</CollectFromChildProcesses>
                        <CollectAspDotNet>False</CollectAspDotNet>

                    </CodeCoverage>
                </Configuration>
            </DataCollector>

        </DataCollectors>
    </DataCollectionRunSettings>
</RunSettings>

Not sure why this section is still here in this output report, when I specified it being skipped in the runsettings file.

NOTE: I'm trying to avoid littering my code with the [ExcludeFromCodeCoverage] attribute and I don't want to have to start adding /p:ExcludeByFile=Program.cs or /p:ExcludeByFile=Startup.cs to my test command in builds, hence using the runsettings file.

1 个答案:

答案 0 :(得分:0)

您不能仅通过提供类名称来使用运行设置文件排除类。

运行设置中的Function元素与

之类的函数/方法的全名匹配

YourNamespace.YourClass.Method(parameters);

from the documentation仅提供以下设置:

  

其他包含或排除元素ModulePath的方式-匹配项   程序集文件路径指定的程序集。

     

CompanyName -通过Company属性匹配程序集。

     

PublicKeyToken -通过公钥令牌匹配已签名的程序集。

     

-通过源文件的路径名匹配元素,其中   它们已定义。

     

属性-匹配具有特定属性的元素   附上。指定属性的全名,并包括   名称末尾的“属性”。

     

功能-完全匹配过程,功能或方法   限定名称。要匹配函数名称,正则表达式必须   与函数的全限定名匹配,包括名称空间,   类名,方法名和参数列表。

您有哪些选择:

选项1:使用以OR开头的方法或使用方法名称

        <Functions>
          <Exclude>

            <!-- Exclude all methods in SampleApp.Program : -->
            <Function>^SampleApp\.Program\..*</Function>

            <!-- Exclude all methods named Main: -->
            <Function>.*\.Main\(.*</Function>
          </Exclude>
        </Functions>

在第一个函数中,请注意,您指定了带有类名称的名称空间,该名称空间以^字符开头。

在第二个功能元素中,请注意,它是通过检查字符串是否以开括号'(')结尾来检查方法名称。

选项2:您可以在类上使用属性,并将其从运行设置文件中排除。

这类似于ExcludeFromCodeCoverate属性。

请注意完整的runsettings file at the end of this documentation page.