Skip to content

Instantly share code, notes, and snippets.

@Zetten
Last active August 30, 2016 13:32
Show Gist options
  • Save Zetten/1e2f26cd48d144c972ba687c27dc25f5 to your computer and use it in GitHub Desktop.
Save Zetten/1e2f26cd48d144c972ba687c27dc25f5 to your computer and use it in GitHub Desktop.
Buck test reports to JUnit XML format
from __future__ import division
import os
from lxml import etree
BUCK2JUNIT_XSLT = '''<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://func"
exclude-result-prefixes="f">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/testcase">
<xsl:variable name="tests" select="count(test)"/>
<xsl:variable name="nonEmptyStacks" select="count(test[@stacktrace != ''])"/>
<xsl:variable name="failures" select="count(test[contains(@stacktrace, 'java.lang.AssertionError')])"/>
<xsl:variable name="skipped" select="count(test[contains(@stacktrace, 'org.junit.internal.AssumptionViolatedException')])"/>
<xsl:variable name="errors" select="$nonEmptyStacks - $failures - $skipped"/>
<testsuite name="{@name}" tests="{$tests}" failures="{$failures}" skipped="{$skipped}" errors="{$errors}">
<xsl:apply-templates/>
</testsuite>
</xsl:template>
<xsl:template match="test">
<testcase classname="{../@name}" name="{@name}" time="{f:toSec(@time)}">
<xsl:choose>
<xsl:when test="contains(@stacktrace, 'java.lang.AssertionError')">
<failure message="{@message}" type="{substring-before(@stacktrace, ':')}">
<xsl:value-of select="@stacktrace"/>
</failure>
</xsl:when>
<xsl:when test="@stacktrace!='' and not(contains(@stacktrace, 'java.lang.AssertionError')) and not(contains(@stacktrace, 'org.junit.internal.AssumptionViolatedException'))">
<error message="{@message}" type="{substring-before(@stacktrace, ':')}">
<xsl:value-of select="@stacktrace"/>
</error>
</xsl:when>
</xsl:choose>
<xsl:apply-templates/>
</testcase>
</xsl:template>
<xsl:template match="stdout">
<system-out><xsl:value-of select="."/></system-out>
</xsl:template>
<xsl:template match="stderr">
<system-err><xsl:value-of select="."/></system-err>
</xsl:template>
</xsl:stylesheet>'''
def toSec(context, time_attr):
return int(time_attr[0]) / 1000
def buck2junit(infile, outfile):
ns = etree.FunctionNamespace("http://func")
ns.prefix = 'f'
ns['toSec'] = toSec
transform = etree.XSLT(etree.XML(BUCK2JUNIT_XSLT))
root = etree.parse(infile)
result = transform(root)
result.write(outfile, pretty_print=True)
@Zetten
Copy link
Author

Zetten commented Aug 30, 2016

The buck2junit.py script is self-contained, but if not registering the toSec function via lxml it could instead be represented in XSL, e.g. following https://github.com/davido/bucklets/blob/master/tools/buckToJUnit.xsl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment