31

I am using the ant tasks 'junit' and 'junitreport' to run my JUnit Tests and generate a report at the end (=> "Unit Test Results").

Is it there some easy way to extend this output somehow to get more information displayed in the report? For example to add an additional column which contains link to a screenshot taken by the test.

I've seen that one could write an own ant junit test runner like the EclipseTestRunner but this is quite some effort. Is there no API to access the elements of a unit report?

skaffman
  • 398,947
  • 96
  • 818
  • 769
blackicecube
  • 1,393
  • 5
  • 15
  • 15
  • what kind of a screen shot are you looking for? you don't just want the stack trace of the error, you're looking for console out, or is it a graphical representation? – Michael Wiles Nov 13 '09 at 10:47
  • 1
    Hi, I don't want to know how to get a screenshot. I already achieved this. What I need to know is how can I extend the JUnit report, so I can include a link to my screenshot. Thanks. – blackicecube Nov 16 '09 at 06:16

3 Answers3

37

The junitreport task uses XSLT to produce the report from the XML files generated by the junittask.

You can customize the output by specifying your own XSLT using the styledir attribute of the nested report element:

<!-- use reportstyle/junit-frames.xsl to produce the report -->
<report styledir="reportstyle" format="frames" todir="testreport"/>

For customizing the the output, one option would be to make a copy of the default XSLT and modify that. Or you could look for an alternative XSLT which is more easy to customize for your purposes.

For small changes, it might be easiest to just import the default XSLT and override whatever templates you need to customize. For example, to add a column for each test, you would need to override the template which produces the table header and the template which produces a table row. Below, I have just copied those templates and modified them a bit to add one column (look for two additions marked with <!-- ADDED -->).

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- import the default stylesheet -->
  <xsl:import href="jar:file:lib/ant-junit.jar!/org/apache/tools/ant/taskdefs/optional/junit/xsl/junit-frames.xsl"/>

  <!-- override the template producing the test table header --> 
  <xsl:template name="testcase.test.header">
    <xsl:param name="show.class" select="''"/>
    <tr valign="top">
      <xsl:if test="boolean($show.class)">
        <th>Class</th>
      </xsl:if>
      <th>Name</th>
      <th>Status</th>
      <th width="80%">Type</th>
      <th nowrap="nowrap">Time(s)</th>

      <!-- ADDED -->
      <th>Screenshot</th>

    </tr>
  </xsl:template>

  <!-- override the template producing a test table row -->
  <xsl:template match="testcase" mode="print.test">
    <xsl:param name="show.class" select="''"/>
    <tr valign="top">
      <xsl:attribute name="class">
        <xsl:choose>
          <xsl:when test="error">Error</xsl:when>
          <xsl:when test="failure">Failure</xsl:when>
          <xsl:otherwise>TableRowColor</xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:variable name="class.href">
        <xsl:value-of select="concat(translate(../@package,'.','/'), '/', ../@id, '_', ../@name, '.html')"/>
      </xsl:variable>
      <xsl:if test="boolean($show.class)">
        <td><a href="{$class.href}"><xsl:value-of select="../@name"/></a></td>
      </xsl:if>
      <td>
        <a name="{@name}"/>
        <xsl:choose>
          <xsl:when test="boolean($show.class)">
            <a href="{concat($class.href, '#', @name)}"><xsl:value-of select="@name"/></a>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@name"/>
          </xsl:otherwise>
        </xsl:choose>
      </td>
      <xsl:choose>
        <xsl:when test="failure">
          <td>Failure</td>
          <td><xsl:apply-templates select="failure"/></td>
        </xsl:when>
        <xsl:when test="error">
          <td>Error</td>
          <td><xsl:apply-templates select="error"/></td>
        </xsl:when>
        <xsl:otherwise>
          <td>Success</td>
          <td></td>
        </xsl:otherwise>
      </xsl:choose>
      <td>
        <xsl:call-template name="display-time">
          <xsl:with-param name="value" select="@time"/>
        </xsl:call-template>
      </td>

      <!-- ADDED -->
      <td>
        <a href="link/to/screenshot/for/test/{@name}">screenshot</a>
      </td>

    </tr>
  </xsl:template>

</xsl:stylesheet>

Here's how the result looks like:

screenshot

martin clayton
  • 76,436
  • 32
  • 213
  • 198
Jukka Matilainen
  • 9,608
  • 1
  • 25
  • 19
  • 2
    Hi, I don't want to apply a different style to my report. I need to extend the report by additional (custom) information. So I have to be able to somehow modify the data of the report, not its style. Thanks. – blackicecube Nov 16 '09 at 06:17
  • The source data for the report produced by the `junitreport` task comes from the XML files generated by the `junit` task. However, based on that data you can add some some extra information to the report. -- For example, if your unit tests produce screenshots in some known location with names that can be derived from the unit test names, it is possible to create links to them by customizing the report style, as in the example above. (I edited the answer to add a screenshot of the end result.) – Jukka Matilainen Nov 16 '09 at 23:10
  • Thanks for your proposition! That's a good approach as start. It's just that I have not only 1 single screenshot per test method but several screenshots, depending on what is tested. So the screenshots are numbered and named, e.g. TestClass-testMethod-01.png. Is there a way with XSLT to "count" the number of screenshots on the file system which "belong" to the test method?. – blackicecube Nov 17 '09 at 07:07
  • 1
    Accessing the file system from XSLT is not really feasible without using extensions. About the only format that is accessible from XSLT 1 is (not surprisingly) XML. Three options that come to my mind at the moment, ranging from the one requiring the least programming to the one requiring the most: ... – Jukka Matilainen Nov 17 '09 at 15:15
  • 3
    ... (1) Put the screenshots into separate directories per test. Then, instead of linking directly to the screenshot, link to the directory. – Jukka Matilainen Nov 17 '09 at 15:16
  • ... or (2) in your Ant build file, generate an XML file listing the screenshots from the file system and access that XML file from XSLT using the `document()` function. – Jukka Matilainen Nov 17 '09 at 15:17
  • ... or (3) Using the `classname` attribute of the `formatter` of the `junit` task, specify your own formatter which includes the information about screenshots in the generated XML. Suppose that your unit tests output the names of the screenshots it creates. I guess it might be possible to extend the default `XMLJUnitResultFormatter` to inspect the output from each test, and write out additional XML tags for each screenshot detected from the output. http://svn.apache.org/viewvc/ant/core/tags/ANT_171/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java?view=markup – Jukka Matilainen Nov 17 '09 at 15:24
0

Also if you don't want to replace the main xsl file, you can copy xsl file into the project root folder, update it with your changes and finally edit your build.xml file adding styledir attribute:

<report styledir="." format="noframes" todir="${junit.output.dir}"/>
0

Awesome ans by Jukka. This is an extension to Jukka's answer as to how exactly you can link the screenshot

  <!-- ADDED -->
  <td>
    <a href="link/to/screenshot/for/test/{@name}">screenshot</a>
  </td>

Instead of above snippet in Jukka's ans, here is how you can link the screenshots :

    <!-- Added screenshot link for failed tests -->
    <td>
        <xsl:variable name="class.name">
            <xsl:value-of select="translate(@classname,'.','/')"/>
        </xsl:variable>
        <xsl:variable name="junit.base">
            <xsl:call-template name="path"><xsl:with-param name="path" select="../@package"/></xsl:call-template>
        </xsl:variable>
    <xsl:choose>
        <xsl:when test="failure">
            <a href="{concat($junit.base,$class.name,'/',@name,'.png')}"><xsl:value-of select="@name"/></a>
        </xsl:when>
        <xsl:when test="error">
            <a href="{concat($junit.base,$class.name,'/',@name,'.png')}"><xsl:value-of select="@name"/></a>
        </xsl:when>
    </xsl:choose>
    </td>

All you need to do after the junit report is generated is - copy all the screenshots from "selenium/screenshots/" directory right under junit_report directory.

The above code will add link only for failed tests. If you want it for all then modify code accordingly.

dganesh2002
  • 1,917
  • 1
  • 26
  • 29