Tuesday, October 21, 2014

A JUnit XSL Transform For PHPUnit Logging

I recently worked on a PHP application with a PHPUnit test suite. Not finding a good way to view the test run results, I settled on logging the output into JUnit format and then applied the style sheet to the XML file so that I can through the XML file into a browser.
time phpunit --testsuite "Application Test Suite" --log-junit public/testresults.xml & sed -i 's//\n/g' public/testresults.xml
Not sure why, but finding a decent transform for the JUnit output was more diffcult than expected. I decided to extended an XSL transform in this StackOverflow answer. It is a pretty good start, plain text, but I can work with it.

After applying Bootstrap styling, the end result is a pleasantly styled JUnit view in a browser. For some reason, FireFox was not applying the bootstrap CSS file, so I just brought in the styles that I needed, thus the style block.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/testsuites">
        <!-- <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text> -->
        <html class="no-js" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <title>PHPUnit Test Results</title>
            <meta name="description" content="" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <!-- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" /> -->
            <style>
                html {
                  font-family: sans-serif;
                  -webkit-text-size-adjust: 100%;
                      -ms-text-size-adjust: 100%;
                  font-size: 10px;
                  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
                }
                body {
                  margin: 0;
                  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
                  font-size: 14px;
                  line-height: 1.42857143;
                  color: #333;
                  background-color: #fff;
                }
                article,
                aside,
                details,
                figcaption,
                figure,
                footer,
                header,
                hgroup,
                main,
                nav,
                section,
                summary {
                  display: block;
                }
                hr {
                  height: 0;
                  -webkit-box-sizing: content-box;
                     -moz-box-sizing: content-box;
                          box-sizing: content-box;
                }
                pre {
                  overflow: auto;
                  font-family: monospace, monospace;
                  font-size: 1em;
                }

                .container {
                  padding-right: 15px;
                  padding-left: 15px;
                  margin-right: auto;
                  margin-left: auto;
                }
                .page-header {
                    padding-bottom: 9px;
                    margin: 40px 0 20px;
                    border-bottom: 1px solid #eee;
                }
                .failure, .error {
                    padding: 0px 20px;
                }
                .failure pre, .error pre {
                    border: 1px solid #DDD;
                    padding: 10px;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <xsl:apply-templates select="testsuite" />
            </div>
        </body>
        </html>
    </xsl:template>

    <xsl:template match="testsuite">
        <header class="page-header">
        <h1>Testsuite: <xsl:value-of select="@name" /></h1>
        <div>
            <xsl:text>
            Tests run: </xsl:text>
            <xsl:value-of select="@tests" />
            <xsl:text>, Failures: </xsl:text>
            <xsl:value-of select="@failures" />
            <xsl:text>, Errors: </xsl:text>
            <xsl:value-of select="@errors" />
            <xsl:text>, Time elapsed: </xsl:text>
            <xsl:value-of select="@time" />
            <xsl:text> sec</xsl:text>
        </div>
        </header>
        <xsl:apply-templates select="system-out" />
        <xsl:apply-templates select="system-err" />
        <div>
            <xsl:apply-templates select="//testcase" />
        </div>
    </xsl:template>

    <xsl:template match="testcase">
        <p>
            <xsl:text>
            Testcase: </xsl:text>
            <xsl:value-of select="@name" />
            <xsl:text> took </xsl:text>
            <xsl:value-of select="@time" />
        </p>
        <xsl:apply-templates select="failure" />
        <xsl:apply-templates select="error" />
    </xsl:template>

    <xsl:template match="failure">
        <div class="failure">
            <span style="color: #ff4136;">
                <xsl:text>
                    Failure:
                </xsl:text>
                <xsl:value-of select="@type" />
            </span>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="error">
        <div class="error">
            <span style="color: #F00;">
                <xsl:text>
                    Error:
                </xsl:text>
                <xsl:value-of select="@type" />
            </span>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="system-out">
        <div>
            <xsl:text>
            ------ Standard output ------
            </xsl:text>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="system-err">
        <div>
            <xsl:text>
            ------ Error output ------
            </xsl:text>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

</xsl:stylesheet>

No comments: