I know Boost can see the filename as when you set the reporter level to detailed and the logger level to all, the filename (even the line number) are shown.
For example, if I call the test executable like
$ ./test --log_level=all --report_level=detailed
I get
Running 1 test case...
Entering test module "simple_class"
/path/to/test_constructor.cpp(28): Entering test suite "simple_class_constructor"
/path/to/test_constructor.cpp(29): Entering test case "default"
/path/to/test_constructor.cpp(30): info: check 'no exceptions thrown by simple_class()' has passed
/path/to/test_constructor.cpp(29): Leaving test case "default"; testing time: 2909us
Leaving test module "simple_class"; testing time: 2955us
Test module "simple_class" has passed with:
1 test case out of 1 passed
1 assertion out of 1 passed
Test suite "simple_class_constructor" has passed with:
1 test case out of 1 passed
1 assertion out of 1 passed
Test case "bool_card_constructor/default" has passed with:
1 assertion out of 1 passed
But if I call the executable like
$ ./test --log_level=all --log_format=JUNIT --report_level=no
I get
<?xml version="1.0" encoding="UTF-8"?>
<testsuite tests="1" skipped="0" errors="0" failures="0" id="0" name="simple_class" time="0.002691">
<testcase assertions="1" classname="simple_class_constructor" name="default" time="0.002217">
<system-out><![CDATA[INFO:
- file : test_constructor.cpp
- line : 30
- message: check 'no exceptions thrown by simple_class()' has passed
]]></system-out>
</testcase>
</testsuite>
In this last format, you can see that the information is inside the system-out
tag, but I want it to be in the testcase
attributes.
Questions
Is there a way to get the filename on which the test suite/case is located on the
testcase
attributes in the JUnit logger on Boost Unit Test?In case is not possible inside Boost Unit Test, is if possible to do the "correction" via shell scripting or similar and how?
CodePudding user response:
You can cross reference with the output of the XML reporter:
build/sotest --log_level=all --log_format=JUNIT --report_level=no
<?xml version="1.0" encoding="UTF-8"?>
<testsuite tests="1" skipped="0" errors="0" failures="1" id="0" name="sotest" time="0.000131">
<testcase assertions="1" classname="Demo" name="Foo" time="0.000114">
<failure message="failure" type="assertion error"><![CDATA[
ASSERTION FAILURE:
- file : test.cpp
- line : 8
- message: check 1==2 has failed
]]></failure><system-err><![CDATA[Failures detected in:
- test case: Demo/Foo
- file: test.cpp
- line: 7
]]></system-err>
</testcase>
</testsuite>
build/sotest --log_level=all --log_format=XML --report_level=no
<TestLog><TestSuite name="sotest"><TestSuite name="Demo" file="/home/sehe/Projects/stackoverflow/test.cpp" line="5"><TestCase name="Foo" file="/home/sehe/Projects/stackoverflow/test.cpp" line="7"><Error file="/home/sehe/Projects/stackoverflow/test.cpp" line="8"><![CDATA[check 1==2 has failed]]></Error><TestingTime>104</TestingTime></TestCase></TestSuite></TestSuite></TestLog>
In fact, the XML output might be what you need!
Demo
Let's use this trivial test:
#define BOOST_TEST_MODULE sotest
#include <boost/test/unit_test.hpp>
#include <boost/test/included/unit_test_framework.hpp>
BOOST_AUTO_TEST_SUITE(SuiteA)
BOOST_AUTO_TEST_CASE(Foo) { BOOST_CHECK(1==2); }
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(SuiteB)
BOOST_AUTO_TEST_CASE(Foo) { BOOST_CHECK(2==3); }
BOOST_AUTO_TEST_SUITE_END()
To use XSLT to correlate both, write both to separate files, e.g.:
sotest --logger=XML,all,b.xml:JUNIT,all,a.xml
Now using saxon-he:
java -jar /home/sehe/custom/Saxon/saxon-he-11.3.jar -xsl:merge.xslt -s:a.xml
Where merge.xslt is a quick and dirty stylesheet I came up with:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="xmlreport_filename" select="'b.xml'"/>
<xsl:variable name="xmlreport" select="document($xmlreport_filename)"/>
<!--<xsl:key name="k1" match="TestLog/TestSuite/TestSuite/TestCase" use="@name"/>-->
<xsl:key name="k1" match="TestCase" use="@name"/>
<xsl:template match="testsuite/testcase">
<xsl:element name="{local-name()}">
<xsl:variable name="expectedclass" select="@classname"/>
<xsl:copy-of select="@*"/>
<!--extra attributes-->
<xsl:for-each select="key('k1', @name, $xmlreport)">
<xsl:if test="..[@name=$expectedclass]">
<xsl:copy-of select="@file|@line"/>
</xsl:if>
</xsl:for-each>
<!--annotating with elements, demonstration-->
<xsl:for-each select="key('k1', @name, $xmlreport)">
<annotation>
<xsl:choose>
<xsl:when test="..[@name=$expectedclass]">
<xsl:copy-of select=".."/>
</xsl:when>
<xsl:otherwise>
<warning reason="mismatched">
<xsl:attribute name='expectedclass'> <xsl:value-of select='$expectedclass'/> </xsl:attribute>
<xsl:attribute name='actualclass'> <xsl:value-of select='../@name'/> </xsl:attribute>
<!--<xsl:copy-of select=".."/>-->
</warning>
</xsl:otherwise>
</xsl:choose>
</annotation>
</xsl:for-each>
<xsl:copy-of select="*"/>
</xsl:element>
</xsl:template>
<xsl:template match="testsuite">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This has the output
<?xml version="1.0" encoding="UTF-8"?>
<testsuite>
<testcase assertions="1"
classname="SuiteA"
name="Foo"
time="0.000107"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="6">
<annotation>
<TestSuite name="SuiteA"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="5">
<TestCase name="Foo"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="6">
<Error file="/home/sehe/Projects/stackoverflow/test.cpp" line="6">check 1==2 has failed</Error>
<TestingTime>107</TestingTime>
</TestCase>
</TestSuite>
</annotation>
<annotation>
<warning reason="mismatched" expected actual/>
</annotation>
<failure message="failure" type="assertion error">
ASSERTION FAILURE:
- file : test.cpp
- line : 6
- message: check 1==2 has failed
</failure>
<system-err>Failures detected in:
- test case: SuiteA/Foo
- file: test.cpp
- line: 6
</system-err>
</testcase>
<testcase assertions="1"
classname="SuiteB"
name="Foo"
time="9.2e-05"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="10">
<annotation>
<warning reason="mismatched" expected actual/>
</annotation>
<annotation>
<TestSuite name="SuiteB"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="9">
<TestCase name="Foo"
file="/home/sehe/Projects/stackoverflow/test.cpp"
line="10">
<Error file="/home/sehe/Projects/stackoverflow/test.cpp" line="10">check 2==3 has failed</Error>
<TestingTime>92</TestingTime>
</TestCase>
</TestSuite>
</annotation>
<failure message="failure" type="assertion error">
ASSERTION FAILURE:
- file : test.cpp
- line : 10
- message: check 2==3 has failed
</failure>
<system-err>Failures detected in:
- test case: SuiteB/Foo
- file: test.cpp
- line: 10
</system-err>
</testcase>
</testsuite>
CAVEAT
Note this happens to work for the simple example, you will have to test/adapt to your real test output.