动态生成代码的代码覆盖率、分析和分析

Posted

技术标签:

【中文标题】动态生成代码的代码覆盖率、分析和分析【英文标题】:Code coverage, analysis and profiling for dynamically generated code 【发布时间】:2013-05-31 05:07:59 【问题描述】:

我有一个演示项目,它创建一个程序集并使用它。我也可以调试注入的代码。但如果我运行覆盖、分析或剖析,它会被计算在内,但我想测量它。

代码:

CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler icc = codeProvider.CreateCompiler();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = false; // debug enabled                
parameters.OutputAssembly = "DynamicCode.dll"; // if specified creates the DLL
parameters.IncludeDebugInformation = true;
CompilerResults results = icc.CompileAssemblyFromFile(parameters, "InjectedCode.cs.txt");

我创建 DLL 来检查生成的 IL 代码。我可以在 VS 中调试代码。但是当我运行覆盖时,如果我使用 TEMP 目录,或者如果我输出 DLL(如上) NO FILE 包含在覆盖中(所以甚至不包括主程序集),生成的程序集就会丢失。

当我运行分析时,我只能看到调用(反射),但看不到生成的代码。当我进行分析时(我在注入的代码中有一些错误,例如没有使用本地变量,并且对所有内容进行了 ofc 分析),注入的代码没有报告任何问题。注入代码:

namespace CodeInjection

    public static class DynConcatenateString
    
        public static string Concatenate(string s1, string s2)
           //  System.Diagnostics.Debugger.Break(); // break here for debugger and also test comment output
            int a = 1+2+3+4+5; // complicated math
            int b = a+2;
            int c = 0;

            return s1 + " !"+b+"! " + s2;
        
    

我想对生成的代码使用覆盖、分析和分析(主要是覆盖)。

【问题讨论】:

【参考方案1】:

VS 2012 中的 Ok 代码覆盖率不完全支持动态生成的代码。

您可以run our analyze command 看到您的模块因同样的原因被跳过,或者是因为缺少符号/p

【讨论】:

也被跳过(这是我在跳过代码覆盖率后的第一次尝试)。 jetbrains 封面和其他工具也错过了。现在我将更深入地讨论这个话题,希望在下周有结果,所以我会发送到这里。请评价我的问题,无论您认为它是否有用。【参考方案2】:

在您的项目中,添加一个新的 xml 文件并将其命名为 dynamic.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>
<!--
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).
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.
It is considered an error to exclude all items from instrumentation as no data would be collected.
-->
              <Include>
                <!-- <ModulePath>.*\\UnitTestProject1\.dll</ModulePath> -->
              </Include>
              <Exclude>
                <ModulePath>.*CPPUnitTestFramework.*</ModulePath>
              </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>

保存。该文件的特别之处在于 CodeCoverage\ModulePaths\Include 部分的 ModulePath 子项已被注释掉。这现在将包括它在代码覆盖中找到的任何 dll。

现在点击测试 -> 测试设置 -> 选择测试设置文件并指定 dynamic.runsettings 文件。您的代码覆盖率现在将使用此自定义设置文件。

单击分析代码覆盖率并运行您想要的任何测试。您应该会在覆盖结果中看到您的 DynamicCode.dll(我在下面隐藏了我的工作站名称):

请注意,我在 .cs.txt 文件中添加了一个名为 BONK 的新方法,它(正确地)显示为 100% 未覆盖。

【讨论】:

以上是关于动态生成代码的代码覆盖率、分析和分析的主要内容,如果未能解决你的问题,请参考以下文章

代码覆盖率和分析之间的区别

白盒测试技术

执行分析后如何将测试结果和代码覆盖率结果发送到 SonarQube 项目

CICD-代码审计(漏洞扫描工具-代码审计静态代码分析和安全检测-代码覆盖率)

运行时代码覆盖工具

python-Coverage 代码覆盖率统计工具,生成html代码报告