.net 使用 .runsettings 从代码覆盖率中排除程序集

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14458246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 16:51:23  来源:igfitidea点击:

Using .runsettings to exclude assemblies from code coverage

.netvisual-studiounit-testingcode-coveragevs-unit-testing-framework

提问by JustAMartin

When running code coverage for my solution which contains multiple projects, I noticed that Code Coverage includes also my test assemblies.

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

I found an article which suggests the following template for .runsettings:

我找到了一篇文章,建议使用以下 .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>

Now the problem is that as soon as I check my .runsettings file in the TEST\Test settings menu, I see Code Coverage analyzes only one of many assemblies in my solution.

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

Even if I remove the line

即使我删除了这条线

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

only one assembly is analyzed. I would like to avoid adding all my assemblies to the Include list, I just need to exclude all the test assemblies.

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

Why does .runsettings make code coverage see only one of the assemblies in my VS solution?

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

回答by Hullah

The issue is the period. For some reason the RegEx is choking on that. You can get around it by escaping the period as follows:

问题是期间。出于某种原因,正则表达式对此感到窒息。您可以通过转义句点来绕过它,如下所示:

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

Also, the empty includes are valid and imply that all Modules are included. The comments of the Microsoft provided sample state that:

此外,空包含是有效的,意味着包含所有模块。微软提供的示例评论指出:

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

回答by sfuqua

On a related note, I ran into this post because I was bit thinking clearly about the regular expression nature of the include and exclude paths. For my WPF application, I wanted to exclude coverage analysis on Caliburn.Micro. So I had written

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

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

Clearly, the period is messing me up. This question does not suffer from that problem, but I bet I'm not the only one to overlook this simple fact. For any other readers, please also take note that * is not a wildcard – it is the regular expression “any number of” operator. You do not want *.Caliburn, but rather .*CaliburnThus this simple statement solved my problem:

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

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

Because it is looking for a path, not just a module name, you need the .* in front of the module to ignore it – that is, you want to ignore it at any given file path.

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

回答by George Helyar

As I couldn't find this answer anywhere else, and this just took me a while to figure out, ModulePathis the full path, and you may be matching your pattern somewhere else in the path.

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

For example, if you have a project Fooand a project Foo.Tests, and they are built to their own directories, you will end up with Foo.Tests\bin\Release\Foo.dlland Foo.Tests\bin\Release\Foo.Tests.dll. This is the dll that the test assembly will reference, so this is the path that is used. Foo\bin\Release\Foo.dllis not directly referenced by the test assembly.

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

If you try to exclude .*tests.*it will match both paths and produce no coverage.

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

To only exclude assemblies with "test" in their file name, ignoring their path, I used

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

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

回答by Peter

I had all sorts of issues getting <ModulePaths>to work reliably (using ASP.NET Core 2.1).

我在<ModulePaths>可靠地工作时遇到了各种各样的问题(使用 ASP.NET Core 2.1)。

In the end I found that using the <Sources>was simple and more reliable and worked exactly as I needed. You still leverage the advice on the use of regex.

最后,我发现使用<Sources>更简单、更可靠,并且完全按照我的需要工作。您仍然可以利用有关使用正则表达式的建议。

I include my solution path, and exclude my \tests subfolders where all my test projects live. Example for CodeCoverage element in RunSettings xml file:

我包括我的解决方案路径,并排除我所有测试项目所在的 \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>

See more at: Customising Code Coverage on MS Docs

查看更多信息:在 MS Docs 上自定义代码覆盖率

回答by Savage

Unfortunately I couldn't get the other answers working for me, but I got this working, as per https://msdn.microsoft.com/en-us/library/jj159530.aspx:

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

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