23

我想尝试 PartCover 的代码覆盖率。我正在使用 MSTest 运行 Visual Studio 2008 Professional。专业版不包括团队测试工具,如代码覆盖率。

所以,我正在尝试 PartCover,但我无法让它工作。在 PartCover.Browser 中,我选择了 MSTest 可执行文件,将工作参数指向了我的 tests.dll,并尝试将工作目录指向 TestResults 文件夹,但出现错误:

“报告为空。检查设置并再次运行目标。”

我不知道下一步该尝试什么。

编辑

事实证明我有两个问题。首先,我的规则不正确。其次,我的工作论证中有空格。空格出现错误,但没有出现在任何地方。

4

5 回答 5

21

是的,我也有这个问题。查看规则字段的格式。

在浏览器中添加如下内容:

+[MyNamespace.MyAssemblyName]*

您指定的程序集名称是包含您想要覆盖的类型的程序集的名称。开始:

+[*]*

并且 partcover 很乐意为您提供单元测试项目的覆盖率指标,您引用的任何库等等。

在命令行中,您在 --include 参数中指定相同的模式: --include=[MyNamespace.MyAssembly]*

您还可以排除包含的命名空间或类型,或限制命名空间内您在报告中获取覆盖率数据的类型。根据手册,规则的格式是正则表达式语法的子集(由 asterix 作为通配符和组成程序集和类名的字符组成,非常有限,但足以获得所需的数据)。查看手册中有关规则的部分。如果您没有手册,请从 sourceforge 下载

于 2008-12-12T18:50:01.863 回答
17

当从 NAnt 脚本调用 PartCover 时,我必须经过许多步骤才能最终让 PartCover 正常工作。为了方便他人,我收集了我必须在这里做的一切;请注意,其中一些已经被其他人回答了,但我花了很多时间把它们放在一起。

首先,正如此处其他地方所回答的那样,如果您的操作系统是 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 即使在其上运行了 CorFlags 后也默默地失败了。但是,2.2 起作用了。

接下来,当调用 PartCover.exe 时,参数的语法是 --arg-name ... 而不是 --=arg-name(即破折号空格 arg 名称,而不是破折号等于 arg 名称);PartCover 文档似乎是双向的,但等号对我不起作用。

在上述之后,PartCover 终于可以从命令行工作了。我使用了一个设置文件(您可以使用 PartCover 浏览器 UI 应用程序保存一个设置文件,然后您可以从命令行使用),因此我指定的唯一参数是设置文件完整路径和输出报告文件命名完整路径。

当从 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>

呸!希望这可以避免其他人让我头疼。

于 2009-12-14T17:05:50.127 回答
3

PartCover 报告也有同样的问题。所以我一直在努力让它正常工作,我发现问题出在 PartCover 发行版附带的两个 XSLT 文件上。

我修复了这些文件,现在一切对我来说都很好:

大会报告

<?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>

希望这个对你有帮助。此外,欢迎任何有关此文件的反馈,因此我们可以为社区提供正确的文件。请参阅此相关问题

于 2010-01-20T07:50:47.010 回答
1

@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) Gáspár Nagy 的 HTML 报告非常好 - http://gasparnagy.blogspot.com/2010/09/detailed-report-for-partcover-in.html

于 2010-11-12T15:53:58.520 回答
0

使用 PartCover 版本 2.3.0.18745 时,我的代码未显示在报告中也有类似问题。使用 2.2.0.34631 版本解决了这个问题。

于 2009-06-16T22:31:08.747 回答