Как заставить PartCover работать - PullRequest
23 голосов
/ 12 декабря 2008

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

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

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

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

Редактировать

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

Ответы [ 5 ]

21 голосов
/ 12 декабря 2008

Да, у меня тоже была эта проблема. Проверьте формат поля Правила.

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

+[MyNamespace.MyAssemblyName]*

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

+[*]*

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

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

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

17 голосов
/ 14 декабря 2009

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

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

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

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

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

Далее, когда вызывается PartCover.exe, синтаксис для аргументов - arg-name ... и NOT - = arg-name (то есть тире тире пробел имя арг, а не тире равно арг имя); документы PartCover, кажется, идут обоими путями, но знак равенства просто не работал для меня.

После вышесказанного PartCover наконец-то работал из командной строки. Я использовал файл настроек (вы можете использовать приложение UI браузера 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>

Уф! Надеюсь, это спасет кого-то еще от головной боли, которая у меня была.

3 голосов
/ 20 января 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>

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

1 голос
/ 12 ноября 2010

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

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

(а) Если вы не хотите внешнего 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

0 голосов
/ 17 июня 2009

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

...