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

20

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

代码:

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代码。我可以在Visual Studio中调试代码。但是当我运行覆盖率测试时,无论是使用TEMP目录还是输出DLL(如上所述),生成的程序集都会被忽略,而且没有任何文件包括在覆盖范围内(即连主要程序集也没有)。当我运行分析时,我只能看到调用(反射)信息,但是没有关于生成代码的内容。当我进行分析时(注入代码中有一些错误,例如未使用局部变量等),注入的代码并没有报告任何问题。注入的代码:
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;
        }
    }
}

我希望在生成的代码上使用覆盖率、分析和性能剖析(主要是覆盖率)。

2个回答

1

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

您可以运行分析命令,以查看由于相同的原因或缺少符号而跳过了您的模块。


还跳过了(这是我在代码覆盖率跳过后的第一次尝试)。JetBrains Cover和其他工具也错过了。现在我正在深入研究这个话题,希望下周能有结果,到时候我会发给你。请评价我的问题,无论您认为它是否有用。 - lajos.cseppento

0
在您的项目中,添加一个新的 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(我已经隐藏了我的工作站名称):

enter image description here

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接