AutoTester999
AutoTester999

Reputation: 616

Get sub-child attribute value traversing child nodes for first match

Each class has 3 or more test methods.

Each test method can pass or fail.

Zero, one or more methods can fail.

The requirement is to traverse through the test-method results, and when a failed method (first match) is found, get the attribute value of 'message' and print it.

If none of the methods failed, then, print blank.

How can I achieve this?


Input.xml
<testng-results>
<suite>
<test>
    <class name="activities.ActivitiesListTest">
    <test-method status="PASS" started-at="2019-02-07T18:24:47Z" name="initTest">
        <reporter-output>
        </reporter-output>
    </test-method>

    <test-method status="FAIL" started-at="2019-02-07T18:24:47Z" name="ActListsForContactShowsContactRelatedTasksTest">
        <exception class="org.openqa.selenium.NoSuchElementException">
            <message>
                <![CDATA[Element with locator 123 not present']]>
            </message>
        </exception>
        <reporter-output>
        </reporter-output>
    </test-method>

    <test-method status="FAIL" started-at="2019-02-07T18:24:47Z" name="afterClass">
        <exception class="org.openqa.selenium.NoSuchElementException">
        <message>
            <![CDATA[Message 3]]>
        </message>
        </exception>
        <reporter-output>
        </reporter-output>
    </test-method>
</class>
</test>
</suite>
</testng-results>

Expected Result:

    <Suite>
    <test failed_reason=" <![CDATA[Element with locator 123 not 
    present']]>"/>
    </Suite>

Tried (XSL):


<Suite>
<xsl:for-each select="/class">
    <test>
        <xsl:attribute name="failed_reason">
            <xsl:choose>
                <xsl:when test="*[@status='FAIL']">test-method[position() = current()]/exception/@message</xsl:when>
            </xsl:choose>
        </xsl:attribute>
    </test>
</xsl:for-each>
</Suite>

Sample absolute path of exception message:

suite/test/class[@name='ActivitiesListForContactShowsContactRelatedTasksTest']/test-method[@name='ActListsTest']/exception/message

But, didn't work.

How to achieve the expected result?

EDIT: Trying Michael's solution.

This is how my XSL currently looks like:


<xsl:template match="/">
<Suite>
    <xsl:for-each select="testng-results/suite/test/class">
        <test>
            <xsl:attribute name="start-time">
                <xsl:value-of select="test-method[1]/@started-at"/>
            </xsl:attribute>
            <xsl:attribute name="failed_reason">
                {normalize-space(test-method[@status='FAIL'][1]/exception/message)}
            </xsl:attribute>
        </test>
    </xsl:for-each>
</Suite>
</xsl:template>

Upvotes: 0

Views: 83

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

I am guessing (!) you want to do something like:

<xsl:template match="/*">
    <Suite>
        <xsl:for-each select="class">
           <test failed_reason="{normalize-space(test-method[@status='FAIL'][1]/exception/message)}"/>
        </xsl:for-each>
    </Suite>
</xsl:template>

Note:

<xsl:for-each select="/class">

will not select anything unless class is the root element. But if class is the root element, then there is only one class - so there's no point in using xsl:for-each.

Upvotes: 1

Related Questions