Подтвердить что ты не робот

Покрытие кода, анализ и профилирование для динамически генерируемого кода

У меня есть демонстрационный проект, который создает сборку и использует ее. Я также могу отлаживать введенный код. Но если я запускаю покрытие, анализ или профилирование, это считается, но я хочу его измерить.

код:

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 включен в зону покрытия (так что даже не главная сборка).

Когда я запускаю профилирование, я могу видеть только вызов (отражение), но ничего о сгенерированном коде. Когда я делаю анализ (у меня есть некоторые ошибки в введенном коде, например, не используемые локальные жители, а также анализ на все), никаких проблем не сообщается из введенного кода. Введенный код:

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;
        }
    }
}

Я хотел бы использовать покрытие, профилирование и анализ сгенерированного кода (в основном для покрытия).

4b9b3361

Ответ 1

Окно покрытия кода в VS 2012 не имеет полной поддержки для динамически генерируемого кода.

Вы можете запустить нашу команду анализа, чтобы увидеть, что ваш модуль был пропущен по этой же причине или это из-за отсутствия символа/р

Ответ 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 отображается в результатах вашего покрытия (я закрыл имя своей рабочей станции ниже):

enter image description here

Обратите внимание, что я добавил новый метод в файл .cs.txt с именем BONK, и он (правильно) отображается на 100% непокрытой.