【问题标题】:Using .runsettings to exclude assemblies from code coverage使用 .runsettings 将程序集排除在代码覆盖范围之外
【发布时间】:2013-01-05 15:57:42
【问题描述】:

在为包含多个项目的解决方案运行代码覆盖率时,我注意到代码覆盖率还包括我的测试程序集。

我发现一篇文章建议使用以下 .runsettings 模板:

<?xml version="1.0" encoding="utf-8"?>
<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>
            <ModulePaths>
              <Include>
                <!-- Do not specify any includes. This will attempt to include all binaries -->
              </Include>
              <Exclude>
                <!-- Exclude modules that aren't to be processed, by their name / path -->
                <ModulePath>.*Tests\.dll$</ModulePath> <!-- I put it here -->
              </Exclude>
            </ModulePaths>

            <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
            <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
            <CollectFromChildProcesses>True</CollectFromChildProcesses>
            <CollectAspDotNet>False</CollectAspDotNet>
            <!--
Additional paths to search for symbol files. Symbols must be found for modules to be instrumented.
If symbols are alongside the binaries, they are automatically picked up. Otherwise specify the here.
Note that searching for symbols increases code coverage runtime. So keep this small and local.

<SymbolSearchPaths>             
  <Path>C:\Users\User\Documents\Visual Studio 11\Projects\ProjectX\bin\Debug</Path>
  <Path>\\mybuildshare\builds\ProjectX</Path>
</SymbolSearchPaths>
-->
            <Functions>
              <Exclude>
                <Function>^std::.*</Function>
                <Function>^ATL::.*</Function>
                <Function>.*::__GetTestMethodInfo.*</Function>
                <Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
                <Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
                <Function>.*::YOU_CAN_ONLY_DESIGNATE_ONE_.*</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>
            <Sources>
              <Exclude>
                <Source>.*\\atlmfc\\.*</Source>
                <Source>.*\\vctools\\.*</Source>
                <Source>.*\\public\\sdk\\.*</Source>
                <Source>.*\\microsoft sdks\\.*</Source>
                <Source>.*\\vc\\include\\.*</Source>
              </Exclude>
            </Sources>
            <CompanyNames>
              <Exclude>
                <CompanyName>.*microsoft.*</CompanyName>
              </Exclude>
            </CompanyNames>
            <PublicKeyTokens>
              <Exclude>
                <PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
                <PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
                <PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
                <PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
                <PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
                <PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
                <PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
              </Exclude>
            </PublicKeyTokens>
          </CodeCoverage>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>

现在的问题是,当我在 TEST\Test 设置菜单中检查我的 .runsettings 文件时,我看到代码覆盖率只分析了我的解决方案中的许多程序集之一。

即使我删除了这条线

 <ModulePath>.*Tests\.dll$</ModulePath> <!-- I put it here -->

只分析一个程序集。我想避免将所有程序集添加到包含列表中,我只需要排除所有测试程序集。

为什么 .runsettings 让代码覆盖率只能看到我的 VS 解决方案中的一个程序集?

【问题讨论】:

  • msdn.microsoft.com/de-de/library/vstudio/jj635153.aspx 表示您可以删除此文件中的每个条目(使用默认值)。尝试从一个空文件开始,然后一个接一个地添加区域。
  • 我遇到了类似的问题,文件更简单。使用默认的运行设置文件,我可以获得代码覆盖率。当我尝试排除第三方库(例如)时,运行代码覆盖率分析结果......什么也没有。没有错误,没有警告,什么都没有。将排除项注释掉,一切都会恢复正常。
  • 只需添加由@habakuk msdn.microsoft.com/en-us/library/vstudio/jj635153.aspx提供的 MSDN 链接的英文版(en-us)

标签: .net visual-studio unit-testing code-coverage vs-unit-testing-framework


【解决方案1】:

&lt;ModulePaths&gt; 可靠地工作(使用 ASP.NET Core 2.1)我遇到了各种各样的问题。

最后,我发现使用&lt;Sources&gt; 更简单、更可靠,并且完全符合我的需要。您仍然可以参考有关使用正则表达式的建议。

我包含了我的解决方案路径,并排除了我所有测试项目所在的 \tests 子文件夹。 RunSettings xml 文件中的 CodeCoverage 元素示例:

<CodeCoverage>
  <Sources>
    <Include>
      <Source>.*\\My\.Solution\.Name\.Space\\.*</Source> <!-- ie: include *\My.Solution.Name.Space\* -->
    </Include>
    <Exclude>
      <Source>.*\\My\.Solution\.Name\.Space\\Tests\\.*</Source> <!-- ie: exclude *\My.Solution.Name.Space\Tests\* -->
    </Exclude>
  </Sources>
  <!-- removed for brevity -->
<CodeCoverage>

查看更多信息:Customising Code Coverage on MS Docs

【讨论】:

    【解决方案2】:

    因为我在其他任何地方都找不到这个答案,而且我花了一段时间才弄清楚,ModulePath 是完整路径,您可能在路径中的其他地方匹配您的模式。

    例如,如果您有一个项目Foo 和一个项目Foo.Tests,并且它们被构建到自己的目录中,那么您最终将得到Foo.Tests\bin\Release\Foo.dllFoo.Tests\bin\Release\Foo.Tests.dll。这是测试程序集将引用的 dll,因此这是使用的路径。 Foo\bin\Release\Foo.dll 未被测试程序集直接引用。

    如果您尝试排除 .*tests.*,它将匹配两个路径并且不会产生覆盖。

    为了只排除文件名中带有“test”的程序集,忽略它们的路径,我使用了

    <Exclude>
      <ModulePath>.*\\[^\\]*test[^\\]*\.dll</ModulePath>
    </Exclude>
    

    【讨论】:

    • "如果您尝试排除 .*tests.* 它将匹配两个路径并且不会产生覆盖。"它确实有这个问题。您的回答节省了我的时间。
    • 谢谢,这需要获得更多的选票。当文件夹路径也可能包含您的命名空间的一部分时,很多这些答案完全忽略了“完整路径”方面,专注于麻烦的点或名称匹配。
    【解决方案3】:

    不幸的是,我无法得到其他答案,但我得到了这个工作,根据https://msdn.microsoft.com/en-us/library/jj159530.aspx

    <ModulePath>.*\\MyProject\.Test\.dll$</ModulePath>
    

    【讨论】:

      【解决方案4】:

      The issue is the period。出于某种原因,RegEx 对此感到窒息。您可以通过转义句点来绕过它,如下所示:

      <ModulePaths>
          <Include>
              <ModulePath>.*MyCompany\.Namespace\.Project\.dll$</ModulePath>
          </Include>
          <Exclude>
              <ModulePath>.*ThirdParty\.Namespace\.Project\.dll$</ModulePath>
          </Exclude>
      </ModulePaths>
      

      此外,空包含是有效的,并暗示所有模块都包含在内。微软的 cmets 提供的示例状态是:

      <!--
      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 http://msdn.microsoft.com/library/2k3te2cs.aspx.
      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.
      -->
      

      【讨论】:

      • 我有 2 个项目和一个解决方案。我需要排除测试项目组装?如何做到这一点
      【解决方案5】:

      在相关的说明中,我遇到了这篇文章,因为我有点清楚地考虑包含和排除路径的正则表达式性质。对于我的 WPF 应用程序,我想排除 Caliburn.Micro 上的覆盖率分析。所以我写了

      <ModulePath>Caliburn.Micro.dll</ModulePath>
      

      显然,这段时间让我很困惑。这个问题不受那个问题的困扰,但我敢打赌,我不是唯一一个忽视这个简单事实的人。对于任何其他读者,还请注意 * 不是通配符 - 它是正则表达式“任意数量”运算符。你不想要*.Caliburn,而是.*Caliburn 因此这个简单的语句解决了我的问题:

      <ModulePath>.*Caliburn.*</ModulePath>
      

      因为它正在寻找一个路径,而不仅仅是一个模块名称,所以您需要模块前面的 .* 来忽略它——也就是说,您想在任何给定的文件路径上忽略它。

      【讨论】:

      • 您的解决方案是正确的。它不是一个简单的通配符或正则表达式,而是一个路径,因此 .* 是强制性的,否则您应该知道 .dll 的完整路径,这在 TFS Azure 中是不可能的。
      猜你喜欢
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 2021-02-12
      相关资源
      最近更新 更多