Нужен XSL-файл для преобразования внутреннего формата XML-тестов в формат Junit (xUnit Plugin для jenkins) - PullRequest
4 голосов
/ 14 июня 2011

Я пытаюсь написать XSL для преобразования моего XML в формат JUNIT, который принимает jenkins (см. Ниже)

мой xml выглядит так: (у меня есть несколько «классов», таких как «центры обработки данных» или «сеть»')

<tests>
   <Datacenters>             
        <test_name>Create NFS Data Center</test_name>
    <end_time>2011-06-13 01:22:55</end_time>
    <iter_num>1</iter_num>
    <start_time>2011-06-13 01:22:52</start_time>
    <status>Pass</status>
   </Datacenters>
   <Datacenters>             
    <test_name>Create NFS Data Center</test_name>
    <end_time>2011-06-13 01:22:55</end_time>
    <iter_num>1</iter_num>
    <start_time>2011-06-13 01:22:52</start_time>
    <status>Pass</status>
   </Datacenters>
   <Network>             
    <test_name>Network test 1</test_name>
    <end_time>2011-06-13 01:22:57</end_time>
    <iter_num>1</iter_num>
    <start_time>2011-06-13 01:22:52</start_time>
    <status>Pass</status>
   </Network>
   .....
 </tests>

Я взял XSL из плагина WebUI и попытался изменить его, я уже на полпути, но все еще сложно.вот что я сделал до сих пор:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">

    <xsl:output method="xml" indent="yes" />    
    <xsl:template match="/">
    <testsuites>        

     <! -- need to change /Datacenters to something else so it will work on all nodes -->
      <xsl:variable name="buildName" select="//tests/Datacenters/test_name"/>   
      <xsl:variable name="numOfTests" select="count(//tests/Datacenters/iter_num)"/>
      <xsl:variable name="numOfFail" select="count(//tests/Datacenters/status [.= 'Fail'])" />  
      <xsl:variable name="numberSkip" select="count(//tests/Datacenters/status [.!='Pass' and .!='Fail'])" />   

 <testsuite name="QE AUTOMATION TESTS [DATACENTERS]"
                tests="{$numberOfTests}" time="0"
                failures="{$numberOfFailures}"  errors="0"
                skipped="{$numberSkipped}">

                <xsl:for-each select="//rest/Datacenters">
                    <xsl:variable name="testName" select="test_name"/>
                    <xsl:variable name="executionId" select="iter_num"/>
                    <xsl:variable name="start_time" select="fn:replace(start_time,' ','T')" />
                    <xsl:variable name="end_time" select="fn:replace(end_time,' ','T')"/>
                    <xsl:variable name="test_parameters" select="test_parameters"/>
                    <xsl:variable name="test_positive" select="test_positive"/>
                    <xsl:variable name="time_diff" select="xs:dateTime($end_time)-xs:dateTime($start_time)"/>
                    <xsl:variable name="duration_seconds" select="seconds-from-duration($time_diff)"/>
                    <xsl:variable name="duration_minutes" select="minutes-from-duration($time_diff)"/>  
                    <xsl:variable name="duration_hours" select="hours-from-duration($time_diff)"/>      
                    <xsl:variable name="outcome" select="status"/>  
                    <xsl:variable name="message" select="$buildName"/>  
                    <!--<xsl:variable name="className" select="Data"/>  -->
                                <testcase classname="Datacenters"
                                    name="{$testName}"
                                    time="{$duration_hours*3600 + $duration_minutes*60 + $duration_seconds }">

                                    <xsl:if test="contains($outcome, 'Fail')"> 
                                        <failure>
                                               test_parameters: <xsl:value-of select="$test_parameters" />
                                               test_positive: <xsl:value-of select="$test_positive" />
                                        </failure>
                                    </xsl:if>
                            </testcase>
                </xsl:for-each>

    </testsuite>
    </testsuites>
        </xsl:template>
    </xsl:stylesheet>

чего я хочу добиться, так это xml:

  <testsuites xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <testsuite name="Datacenters" tests="2" time="4" failures="0" errors="0" skipped="0">
            <testcase classname="Datacenters" name="Create NFS Data Center" time="3"/>
            <testcase classname="Datacenters" name="Create ISCSI Data Center" time="1"/>
        </testsuite>
        <testsuite name="Network" tests="1" time="5" failures="0" errors="0" skipped="0">
            <testcase classname="Datacenters" name="Network test 1" time="5"/>
        </testsuite>
    </testsuites>

, но я не знаю, как перебирать все "классы""поэтому вместо жесткого" ЦОД "я хочу представить всех существующих потомков <tests>

1 Ответ

5 голосов
/ 15 июня 2011

Я собираюсь просто ответить на комментарий внутри шаблона (возможно, ваш код нуждается в отладке и рефакторинге):

   <!-- need to change /Datacenters to something 
          else so it will work on all nodes -->

Чтобы избежать жесткого кодирования:

1) заменить XPath следующим образом:

//tests/Datacenters/test_name

с //tests/*/test_name

2) Исправить итерацию (совершенно неверно), должно быть:

<xsl:for-each select="//tests/Datacenters">

и вы хотите:

 <xsl:for-each select="//tests/*">

3) Наконец, замените:

 <testcase classname="Datacenters">

с

 <testcase classname="{local-name(.)}">

Редактировать после комментариев

Я собираюсь ответить с упрощенным выводом, просто чтобы показать вам, как работает группировка в XSLT 2.0 . Надеюсь, что этот ответ приемлем для вас, ваш настоящий шаблон немного сложно проверить здесь:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output indent="yes"/>

    <xsl:template match="tests">
        <testsuites>
            <xsl:for-each-group select="*" group-by="local-name()">
                <testsuite name="{current-grouping-key()}">
                    <xsl:for-each   select="current-group()">
                        <testcase classname="{current-grouping-key()}"/>
                    </xsl:for-each>
                </testsuite>
            </xsl:for-each-group>
        </testsuites>   
    </xsl:template>

</xsl:stylesheet>

, примененное к входной выборке, указанной в вашем вопросе, дает:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
   <testsuite name="Datacenters">
      <testcase classname="Datacenters"/>
      <testcase classname="Datacenters"/>
   </testsuite>
   <testsuite name="Network">
      <testcase classname="Network"/>
   </testsuite>
</testsuites>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...