Getting your MSTEST unit test stdout to show in Jenkins
There is no easy way to say it, the default Jenkins plugin for publishing MSTEST results does not show a unit test's standard output when it fails.
Should you decide you want your standard output shown after all, you'll need to edit the XSLT used to transform the MSTEST result format (trx) into JUnit's format (which is then parsed by Jenkins and finally displayed in its web interface).
To edit this XSLT, search for "mstest-to-junit.xsl" in your Jenkins home directory.
. . . \Jenkins\plugins\mstest\WEB-INF\classes\hudson\plugins\mstest\mstest-to-junit.xsl
Back it up just in case, and copy-paste the following xslt code into it. Restart Jenkins and enjoy your standard output upon test failure.
Hooah!
Should you decide you want your standard output shown after all, you'll need to edit the XSLT used to transform the MSTEST result format (trx) into JUnit's format (which is then parsed by Jenkins and finally displayed in its web interface).
To edit this XSLT, search for "mstest-to-junit.xsl" in your Jenkins home directory.
. . . \Jenkins\plugins\mstest\WEB-INF\classes\hudson\plugins\mstest\mstest-to-junit.xsl
Back it up just in case, and copy-paste the following xslt code into it. Restart Jenkins and enjoy your standard output upon test failure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a ="http://microsoft.com/schemas/VisualStudio/TeamTest/2006" xmlns:b ="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" > | |
<xsl:output method="xml" indent="yes" /> | |
<xsl:template match="/"> | |
<testsuites> | |
<xsl:variable name="buildName" select="//a:TestRun/@name"/> | |
<xsl:variable name="numberOfTests" select="count(//a:UnitTestResult/@outcome) + count(//b:UnitTestResult/@outcome)"/> | |
<xsl:variable name="numberOfFailures" select="count(//a:UnitTestResult/@outcome[.='Failed']) + count(//b:UnitTestResult/@outcome[.='Failed'])" /> | |
<xsl:variable name="numberSkipped" select="count(//a:UnitTestResult/@outcome[.!='Passed' and .!='Failed']) + count(//b:UnitTestResult/@outcome[.!='Passed' and .!='Failed'])" /> | |
<testsuite name="MSTestSuite" | |
tests="{$numberOfTests}" time="0" | |
failures="{$numberOfFailures}" errors="0" | |
skipped="{$numberSkipped}"> | |
<xsl:for-each select="//a:UnitTestResult"> | |
<xsl:variable name="testName" select="@testName"/> | |
<xsl:variable name="executionId" select="@executionId"/> | |
<xsl:variable name="duration_seconds" select="substring(@duration, 7)"/> | |
<xsl:variable name="duration_minutes" select="substring(@duration, 4,2 )"/> | |
<xsl:variable name="duration_hours" select="substring(@duration, 1, 2)"/> | |
<xsl:variable name="outcome" select="@outcome"/> | |
<xsl:variable name="message" select="a:Output/a:ErrorInfo/a:Message"/> | |
<xsl:variable name="stacktrace" select="a:Output/a:ErrorInfo/a:StackTrace"/> | |
<!--The magic takes place here, save the StdOut of the test to a variable. | |
Later, put it in the failure message emitted by the failure tag. --> | |
<xsl:variable name="output" select="a:Output/a:StdOut"/> | |
<xsl:for-each select="//a:UnitTest"> | |
<xsl:variable name="currentExecutionId" select="a:Execution/@id"/> | |
<xsl:if test="$currentExecutionId = $executionId" > | |
<xsl:variable name="className" select="substring-before(a:TestMethod/@className, ',')"/> | |
<testcase classname="{$className}" | |
name="{$testName}" | |
time="{$duration_hours*3600 + $duration_minutes*60 + $duration_seconds }"> | |
<xsl:if test="contains($outcome, 'Failed')"> | |
<failure> | |
MESSAGE: | |
<xsl:value-of select="$message" /> | |
+++++++++++++++++++ | |
Output: | |
<xsl:value-of select="$output" /> | |
+++++++++++++++++++ | |
STACK TRACE: | |
<xsl:value-of select="$stacktrace" /> | |
</failure> | |
</xsl:if> | |
</testcase> | |
</xsl:if> | |
</xsl:for-each> | |
</xsl:for-each> | |
<xsl:for-each select="//b:UnitTestResult"> | |
<xsl:variable name="testName" select="@testName"/> | |
<xsl:variable name="executionId" select="@executionId"/> | |
<xsl:variable name="testId" select="@testId"/> | |
<xsl:variable name="duration_seconds" select="substring(@duration, 7)"/> | |
<xsl:variable name="duration_minutes" select="substring(@duration, 4,2 )"/> | |
<xsl:variable name="duration_hours" select="substring(@duration, 1, 2)"/> | |
<xsl:variable name="outcome" select="@outcome"/> | |
<xsl:variable name="message" select="b:Output/b:ErrorInfo/b:Message"/> | |
<xsl:variable name="stacktrace" select="b:Output/b:ErrorInfo/b:StackTrace"/> | |
<!--The magic takes place here, save the StdOut of the test to a variable. | |
Later, put it in the failure message emitted by the failure tag. --> | |
<xsl:variable name="output" select="b:Output/b:StdOut"/> | |
<xsl:for-each select="//b:UnitTest"> | |
<xsl:variable name="currentTestId" select="@id"/> | |
<xsl:if test="$currentTestId = $testId" > | |
<xsl:variable name="className" select="substring-before(b:TestMethod/@className, ',')"/> | |
<testcase classname="{$className}" | |
name="{$testName}" | |
time="{$duration_hours*3600 + $duration_minutes*60 + $duration_seconds }"> | |
<xsl:if test="contains($outcome, 'Failed')"> | |
<failure> | |
MESSAGE: | |
<xsl:value-of select="$message" /> | |
+++++++++++++++++++ | |
Output: | |
<xsl:value-of select="$output" /> | |
+++++++++++++++++++ | |
STACK TRACE: | |
<xsl:value-of select="$stacktrace" /> | |
</failure> | |
</xsl:if> | |
</testcase> | |
</xsl:if> | |
</xsl:for-each> | |
</xsl:for-each> | |
</testsuite> | |
</testsuites> | |
</xsl:template> | |
</xsl:stylesheet> |
Hooah!
Comments
Post a Comment