Как заставить PartCover работать

Я хочу попробовать PartCover для покрытия кода. Я запускаю Visual Studio 2008 Professional с MSTest. Профессиональная версия не включает инструменты группового тестирования, такие как покрытие кода.

Итак, я пробую PartCover, но не могу заставить его работать. В PartCover.Browser я выбрал исполняемый файл MSTest, указал рабочие аргументы на свой tests.dll и попытался указать рабочий каталог в папку TestResults, но получаю сообщение об ошибке:

«Отчет пуст. Проверьте настройки и снова запустите цель».

Я не знаю, что попробовать дальше.

Изменить

Оказывается, у меня было две проблемы. Во-первых, я неправильно изложил свои правила. Во-вторых, у меня были пробелы в моих рабочих аргументах. Пробелы давали ошибку, но нигде не отображались.


person sgwill    schedule 12.12.2008    source источник
comment
Здесь можно найти отличное пошаговое руководство, хотя оно предназначено для NUnit, а не для MSTest: csharpcity.com/using-partcover-and-nunit-for-code-coverage   -  person Lucas B    schedule 24.09.2010


Ответы (5)


Да, у меня тоже была эта проблема. Ознакомьтесь с форматом поля «Правила».

В браузере добавьте что-то вроде:

+[MyNamespace.MyAssemblyName]*

Указываемое вами имя сборки - это имя сборки, содержащей типы, для которых требуется покрытие. Начните с:

+[*]*

и partcover с радостью предоставит вам метрики покрытия для проекта модульного тестирования, любых библиотек, на которые вы ссылаетесь, и так далее.

В командной строке вы указываете тот же шаблон в аргументе --include: --include=[MyNamespace.MyAssembly]*

Вы также можете исключить содержащиеся пространства имен или типы или ограничить типы из пространства имен, для которых вы получаете данные о покрытии в отчете. Формат правил - это подмножество синтаксиса регулярных выражений в соответствии с руководством (состоящее из звездочки в качестве подстановочного знака и символов, составляющих имена сборок и классов, что довольно ограничено, но достаточно, чтобы получить нужные данные). Ознакомьтесь с разделом правил в руководстве. Если у вас нет руководства, загрузите его с sourceforge.

person Hamish Smith    schedule 12.12.2008
comment
PartCover слишком громоздок в установке. Это может быть бесплатно, но это огромная головная боль по сравнению с nCover - особенно в Testdriven .NET. - person Damien; 22.08.2009
comment
Я бы поспорил с этим - PartCover.exe --target YourProgram.exe довольно просто сделать. - person JBRWilkinson; 15.09.2009
comment
@ Дэмиен, вряд ли это серьезная головная боль. Я только что нашел Хэмиш ответ на бит, на котором я застрял, и через 10 секунд он работает с NUnit. - person RichardOD; 20.11.2009
comment
Обратите внимание, что последняя версия partcover с поддержкой .NET4 теперь размещена здесь github.com/sawilde/partcover .net4 - person Shaun Wilde; 09.08.2011

Мне пришлось пройти несколько шагов, чтобы наконец заставить работать PartCover при вызове его из сценария NAnt. Я собрал здесь все, что должен был сделать, для удобства других; Обратите внимание, что на некоторые из этих вопросов уже ответили другие, но я потратил массу времени, чтобы собрать все воедино.

Во-первых, как здесь сказано в другом месте, если ваша ОС 64-разрядная, вам необходимо запустить [самый последний Windows SDK] \ bin \ CorFlags.exe [каталог установки PartCover] \ PartCover.exe / 32BIT + / Force

Это однократный шаг после установки PartCover. Он изменит исполняемый файл и предупредит вас, что сборку необходимо будет повторно подписать, но я этого не делал, и она (в конечном итоге) сработала нормально. Обратите внимание, что хотя похоже, что CorFlags не выполнил то, что вы просили, и предупредил вас о подписании, он изменил .exe, он просто не указывает на это явно.

Затем, опять же, если ваша ОС 64-разрядная и вы используете NUnit (или другой тестовый exe) с PartCover, вам нужно будет вызвать версию, явно скомпилированную для x86. В случае NUnit это будет nunit-console-x86.exe. Вызов nunit-console.exe просто зависал для меня на неопределенное время после выполнения работы и не возвращался к приглашению.

Далее, как также ответили в другом месте здесь, PartCover 2.3, сборка для разработчиков, молча выходила из строя даже после запуска на ней CorFlags. Однако 2.2 сработала.

Затем, когда вызывается PartCover.exe, синтаксис аргументов - имя-аргумента ... и НЕ - = имя-аргумента (т.е. Документы PartCover, кажется, идут в обоих направлениях, но знак равенства просто не работает для меня.

После вышесказанного PartCover наконец-то заработал из командной строки. Я использовал файл настроек (вы можете использовать приложение пользовательского интерфейса браузера PartCover для сохранения файла настроек, который затем можно использовать из командной строки), так что единственными аргументами, которые я указал, были полный путь к файлу настроек и файл выходного отчета. имя полный путь.

Это все еще не работало при вызове из сценария NAnt, поэтому я наконец понял, что значения arg должны быть заключены в кавычки ... и использовать токены в кодировке HTML для кавычек. Таким образом...

Нет выдержки:

<property name="PartCoverExePath" value="c:\Program Files (x86)\PartCover .NET 2\PartCover.exe" />
<property name="PartCoverWorkPath" value="c:\Projects\MyProject\trunk\CI\" />
<property name="PartCoverSettingsFileName" value="PartCover.Settings.xml" />
<property name="PartCoverReportFileName" value="PartCover.Report.xml" />

<target name="MyTarget">
<exec program="${PartCoverExePath}">
<arg value="--settings &quot;${PartCoverWorkPath}${PartCoverSettingsFileName}&quot;" />
<arg value="--output &quot;${PartCoverWorkPath}${PartCoverReportFileName}&quot;" />
</exec>
</target>

И файл настроек PartCover:

<PartCoverSettings>
<Target>C:\CI\Binaries\NUnit2.5.2\bin\net-2.0\nunit-console-x86.exe</Target>
<TargetWorkDir>c:\Projects\MyProject\trunk\MyProject.Test\bin\Debug</TargetWorkDir>
<TargetArgs>MyProject.Test.dll</TargetArgs>
<Rule>+[*]*</Rule>
<Rule>-[log4net*]*</Rule>
<Rule>-[nunit*]*</Rule>
<Rule>-[MyProject.Test*]*</Rule>
</PartCoverSettings>

Фух! Надеюсь, это избавит кого-нибудь от головной боли, которая у меня была.

person pelazem    schedule 14.12.2009
comment
+1! Я был с ума сойти, пытаясь настроить его через командную строку. Использование графического интерфейса и экспорт настроек было отличной идеей! Спасибо! - person Steven Evers; 12.05.2010

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

Я исправил эти файлы, и теперь у меня все работает нормально:

отчет по сборкам

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt">
  <xsl:output method="html" indent="yes"/>
    <xsl:template match="/">

    <xsl:variable name="cov0style" select="'background:#E79090;text-align:right;'"/>
    <xsl:variable name="cov20style" select="'background:#D79797;text-align:right;'"/>
    <xsl:variable name="cov40style" select="'background:#D7A0A0;text-align:right;'"/>
    <xsl:variable name="cov60style" select="'background:#C7A7A7;text-align:right;'"/>
    <xsl:variable name="cov80style" select="'background:#C0B0B0;text-align:right;'"/>
    <xsl:variable name="cov100style" select="'background:#D7D7D7;text-align:right;'"/>

<table style="border-collapse: collapse;">
  <tr style="font-weight:bold; background:whitesmoke;">
    <td colspan="2">Coverage by assembly</td>
  </tr>

  <xsl:variable name="asms" select="/PartCoverReport/Assembly"/>
  <xsl:for-each select="$asms">
    <xsl:variable name="current-asm-node" select="."/>
    <tr>

      <xsl:element name="td">
        <xsl:attribute name="style">background:ghostwhite; padding: 5px  30px 5px  5px;</xsl:attribute>
        <xsl:value-of select="$current-asm-node/@name"/>
      </xsl:element>

      <xsl:variable name="codeSize" select="sum(/PartCoverReport/Type[@asmref=$current-asm-node/@id]/Method/pt/@len)+0"/>
      <xsl:variable name="coveredCodeSize" select="sum(/PartCoverReport/Type[@asmref=$current-asm-node/@id]/Method/pt[@visit>0]/@len)+0"/>

      <xsl:element name="td">
        <xsl:if test="$codeSize=0">
          <xsl:attribute name="style">
            <xsl:value-of select="$cov0style"/>
          </xsl:attribute>
          0%
        </xsl:if>
        <xsl:if test="$codeSize &gt; 0">
          <xsl:variable name="coverage" select="ceiling(100 * $coveredCodeSize div $codeSize)"/>
          <xsl:if test="$coverage &gt;=  0 and $coverage &lt; 20">
            <xsl:attribute name="style">
              <xsl:value-of select="$cov20style"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$coverage &gt;= 20 and $coverage &lt; 40">
            <xsl:attribute name="style">
              <xsl:value-of select="$cov40style"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$coverage &gt;= 40 and $coverage &lt; 60">
            <xsl:attribute name="style">
              <xsl:value-of select="$cov60style"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$coverage &gt;= 60 and $coverage &lt; 80">
            <xsl:attribute name="style">
              <xsl:value-of select="$cov80style"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$coverage &gt;= 80">
            <xsl:attribute name="style">
              <xsl:value-of select="$cov100style"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:value-of select="$coverage"/>%
        </xsl:if>
      </xsl:element>
    </tr>
  </xsl:for-each>
</table>

отчет по классам

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt">
<xsl:output method="html" indent="no"/>

<xsl:template match="/">

<xsl:variable name="cov0style" select="'background:#FF4040;text-align:right;'"/>
<xsl:variable name="cov20style" select="'background:#F06060;text-align:right;'"/>
<xsl:variable name="cov40style" select="'background:#E78080;text-align:right;'"/>
<xsl:variable name="cov60style" select="'background:#E0A0A0;text-align:right;'"/>
<xsl:variable name="cov80style" select="'background:#D7B0B0;text-align:right;'"/>
<xsl:variable name="cov100style" select="'background:#E0E0E0;text-align:right;'"/>

<table style="border-collapse: collapse;">
    <tr style="font-weight:bold; background:whitesmoke;"><td colspan="2">Coverage by class</td></tr>

    <xsl:for-each select="/PartCoverReport/Type">
        <tr>

            <xsl:element name="td">
                <xsl:attribute name="style">background:ghostwhite; padding: 5px  30px 5px  5px;</xsl:attribute>
                <xsl:value-of select="@name"/>
            </xsl:element>

            <xsl:variable name="codeSize" select="sum(./Method/pt/@len)+0"/>
            <xsl:variable name="coveredCodeSize" select="sum(./Method/pt[@visit>0]/@len)+0"/>

            <xsl:element name="td">
                <xsl:if test="$codeSize=0">
                    <xsl:attribute name="style"><xsl:value-of select="$cov0style"/></xsl:attribute>
                    0%
                </xsl:if>

                <xsl:if test="$codeSize &gt; 0">
                    <xsl:variable name="coverage" select="ceiling(100 * $coveredCodeSize div $codeSize)"/>

                    <xsl:if test="$coverage &gt;=  0 and $coverage &lt; 20"><xsl:attribute name="style"><xsl:value-of select="$cov20style"/></xsl:attribute></xsl:if>
                    <xsl:if test="$coverage &gt;= 20 and $coverage &lt; 40"><xsl:attribute name="style"><xsl:value-of select="$cov40style"/></xsl:attribute></xsl:if>
                    <xsl:if test="$coverage &gt;= 40 and $coverage &lt; 60"><xsl:attribute name="style"><xsl:value-of select="$cov60style"/></xsl:attribute></xsl:if>
                    <xsl:if test="$coverage &gt;= 60 and $coverage &lt; 80"><xsl:attribute name="style"><xsl:value-of select="$cov80style"/></xsl:attribute></xsl:if>
                    <xsl:if test="$coverage &gt;= 80"><xsl:attribute name="style"><xsl:value-of select="$cov100style"/></xsl:attribute></xsl:if>
                    <xsl:value-of select="$coverage"/>%
                </xsl:if>

            </xsl:element>
        </tr>
    </xsl:for-each>
</table>    
</xsl:template>
</xsl:stylesheet>

Я надеюсь, вы найдете это полезным. Также приветствуются любые отзывы об этих файлах, поэтому мы можем предоставить сообществу правильные файлы. См. этот связанный вопрос

person yeyeyerman    schedule 20.01.2010
comment
Спасибо за это, хотя процентные значения не соответствуют тому, что я получаю в браузере, поэтому я не думаю, что они работают правильно. - person Chris Nicola; 18.06.2010

@pelazm - Спасибо за отличное руководство.

Две незначительные вещи, которые нужно добавить к вашему решению:

(a) Если вам не нужен внешний PartCover.settings.xml

<!-- Runs unit tests through PartCover to calculate unit test covereage-->
<!-- Use %2a instead of * and %3f instead of ? to prevent expansion -->
<!-- %40 = @  %25 = % %24 = $ -->
<Target Name="RunTests">
  <ItemGroup>
     <pc4_settings Include="--target &quot;$(NUnitEXE)&quot;"/>
     <pc4_settings Include="--target-work-dir &quot;$(RootDirectory)\src&quot;"/>
     <pc4_settings Include="--include [%2a]%2a"/>
     <pc4_settings Include="--exclude [nunit%2a]%2a"/>
     <pc4_settings Include="--exclude [log4net%2a]%2a"/>
     <pc4_settings Include="--exclude [MetadataProcessor.Tests%2a]%2a"/>
   </ItemGroup>

   <CreateItem Include="$(RootDirectory)\src\**\bin\$(Configuration)\*.Tests.dll">
     <Output TaskParameter="Include" ItemName="TestAssemblies" />
   </CreateItem>

   <Exec Command="&quot;$(PartCover4Directory)\PartCover.exe&quot; --register    @(pc4_settings,' ') --target-args &quot;%(TestAssemblies.Identity) $(NUnitArgs) /xml:%(TestAssemblies.Identity).NUnitResults.xml&quot; --output $(BuildDirectory)\PartCover-results.xml"
  ContinueOnError="true"
  WorkingDirectory="$(BuildDirectory)">
     <Output TaskParameter="ExitCode" ItemName="ExitCodes"/>
   </Exec>

   <XslTransformation XslInputPath="$(RootDirectory)\tools\partcover4\xslt\PartCoverFullReport.xslt"
                  XmlInputPaths="$(BuildDirectory)\PartCover-results.xml"
                  OutputPaths="$(BuildDirectory)\PartCover-results-PartCoverFullReport.html" />

   <Error Text="Test error occurred" Condition="'%(ExitCodes.Identity)'>0"/>
 </Target>

(b) HTML-отчет Гаспара Надя довольно хорош - http://gasparnagy.blogspot.com/2010/09/detailed-report-for-partcover-in.html

person Community    schedule 12.11.2010

У меня были аналогичные проблемы с моим кодом, который не отображался в отчете при использовании PartCover версии 2.3.0.18745. Использование версии 2.2.0.34631 решило проблему.

person Dan Nuffer    schedule 16.06.2009