Skip to topic | Skip to bottom
Home
Public


Currently logged in as TWikiGuest?

Public.MigrateFromTestTrackProToBugzillar1.2 - 12 Jul 2005 - 18:32 - KevinJarnottopic end

Start of topic | Skip to actions

How to Migrate from TestTrack Pro to Bugzilla

I had decided to migrate my engineering group from Seapine's expensive TestTrack Pro product (version 5) to the free Bugzilla defect tracking system (version 2.18.1). Here's an overview of how I did it.

Export Test Track Pro database to XML file

Easy enough - click on XML Export and save the defects to an XML file.

Transform the TT XML file to Bugzilla's XML format

I used the XSLT Library for GNOME under http://www.cygwin.org. Other EXSLT-compliant XSLT processors should also work.

xsltproc -o out.xml tt2bz.xsl tt.xml

where out.xml is the output XML file (defects in Bugzilla XML format), tt2bz.xsl is the script listed below, and tt.xml is the file containing the exported TestTrack defects.

Load the defects into Bugzilla

Bugzilla comes with a Perl script named importxml.pl. Simply run:

perl importxml.pl out.xml

The defects should (hopefully) now be imported into Bugzilla.

The XSLT script

This will require some modification to fit your needs/data.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"      
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="exsl str"      
version="1.0">

<xsl:output method="xml"/>

<!-- Update this mapping with your data.  It maps TT usernames to BZ accts. -->
<xsl:variable name="emailMap">
<map ln="User1" email="user1@domain.com"/>
<map ln="User2" email="user2@domain.com"/>
<map ln="User3" email="usere@domain.com"/>
</xsl:variable>
<xsl:variable name="emailmaps" select="exsl:node-set($emailMap)/map"/>


<!-- Update this mapping with your data.  It maps TT products/components to BZ's -->
<xsl:variable name="prodMap">
<map ttprod="TT Product1"         ttcomp="*" bzprod="BZ - Product1" bzcomp="BZ - Comp1"/>
<map ttprod="TT Product2"         ttcomp="*" bzprod="BZ - Product1" bzcomp="BZ - Comp2"/>
</xsl:variable>
<xsl:variable name="prodmaps" select="exsl:node-set($prodMap)/map"/>

<xsl:template match="/TestTrackData">
<bugzilla version="2.18.1" urlbase="http://domain.com/testtrack/" maintainer="me@domain.com" exporter="me@domain.com">
<xsl:apply-templates select="defect"/>
</bugzilla>
</xsl:template>

<xsl:template match="defect">
<xsl:variable name="_finalData">
<xsl:apply-templates select="*" mode="normalize"/>
</xsl:variable>
<xsl:variable name="finalData" select="exsl:node-set($_finalData)"/>

<bug>
<!-- Explicitly apply templates to preserve ordering in BZ data -->
<!--       -->
<xsl:apply-templates select="$finalData/defect-number"/>
<xsl:apply-templates select="$finalData/defect-date"/>
<xsl:apply-templates select="$finalData/summary"/>
<xsl:apply-templates select="$finalData/date-last-modified"/>
<!-- 1 -->
<!-- 1     -->
<xsl:apply-templates select="$finalData/product"/>
<xsl:apply-templates select="$finalData/component"/>
<version>unspecified</version>
<rep_platform>Other</rep_platform>
<op_sys>other</op_sys>
<xsl:apply-templates select="$finalData/defect-status"/>
<xsl:apply-templates select="$finalData/priority"/>
<xsl:apply-templates select="$finalData/severity"/>
<target_milestone>---</target_milestone>
<xsl:apply-templates select="$finalData/entered-by/email-address"/>
<!--       -->
<xsl:apply-templates select="$finalData/currently-assigned-to"/>
<xsl:apply-templates select="$finalData/reported-by-record/description"/>
<xsl:apply-templates select="$finalData/*/notes"/>
</bug>
</xsl:template>

<xsl:template match="*" mode="normalize">
<xsl:copy>
<xsl:apply-templates select="* | text()" mode="normalize"/>
</xsl:copy>
</xsl:template>

<xsl:template match="text()" mode="normalize">
<xsl:copy-of select="."/>
</xsl:template>

<xsl:template match="foo" mode="normalize">
<foo>
<!-- Add attributes, other elements, transform this element, format it, whatever -->
</foo>
</xsl:template>

<xsl:template match="defect-number">
<bug_id><xsl:value-of select="."/></bug_id>
</xsl:template>

<xsl:template match="summary">
<short_desc><xsl:value-of select="."/></short_desc>
</xsl:template>

<xsl:template match="product">
<xsl:variable name="_prod" select="."/>
<xsl:variable name="_comp" select="../component"/>

<xsl:comment>Prod: <xsl:value-of select="$_prod"/></xsl:comment>
<xsl:comment>Comp: <xsl:value-of select="$_comp"/></xsl:comment>

<!-- Handle special case (reverse) lookup for DXMark -->
<xsl:variable name="comp">
<xsl:choose>
<xsl:when test="$_prod = 'DXMark'">
<xsl:value-of select="$prodmaps[@ttcomp = $_comp]/@bzcomp"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prodmaps[@ttprod = $_prod]/@bzcomp"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="_prodlookup" select="$prodmaps[@ttprod = $_prod]/@bzprod"/>
<product><xsl:value-of select="$_prodlookup"/></product>
<component><xsl:value-of select="$comp"/></component>
</xsl:template>

<xsl:template match="priority">
<xsl:comment>Prio: <xsl:value-of select="."/></xsl:comment>

<priority>
<xsl:choose>
<xsl:when test=". = '** Show-stopper **'">P1</xsl:when>
<xsl:when test=". = 'Immediate'">P2</xsl:when>
<xsl:when test=". = 'Soon'">P3</xsl:when>
<xsl:when test=". = 'Later'">P4</xsl:when>
<xsl:when test=". = 'Future Release'">P5</xsl:when>
</xsl:choose>
</priority>
</xsl:template>

<!-- RESOLUTION/STATUS -->

<!-- Default map for resolutions.  -->
<xsl:template match="defect-status" mode="resolution-map"/>

<!-- Map for defect-status is "Closed" or "Fixed" -->
<xsl:template match="defect-status[contains(., 'Closed') or contains(., 'Fixed')]" mode="resolution-map">
<map bzstatus="CLOSED" ttres="Code Change" bzres="FIXED"/>
<map bzstatus="CLOSED" ttres="Documentation Change" bzres="FIXED"/>
<map bzstatus="CLOSED" ttres="Clarification" bzres="FIXED"/>
<map bzstatus="CLOSED" ttres="Not Out Bug" bzres="INVALID"/>
<map bzstatus="CLOSED" ttres="Not a Bug" bzres="INVALID"/>
<map bzstatus="CLOSED" ttres="On Hold" bzres="LATER"/>
<map bzstatus="CLOSED" ttres="Duplicate" bzres="DUPLICATE"/>
</xsl:template>

<xsl:template match="defect-status[. = 'Open']">
<bug_status>ASSIGNED</bug_status>
</xsl:template>

<!-- Map for defect-status is "Released to Testing" -->
<xsl:template match="defect-status[. = 'Released to Testing']" mode="resolution-map">
<map bzstatus="RESOLVED" ttres="Code Change" bzres="FIXED"/>
<map bzstatus="RESOLVED" ttres="Documentation Change" bzres="FIXED"/>
<map bzstatus="RESOLVED" ttres="Clarification" bzres="FIXED"/>
<map bzstatus="RESOLVED" ttres="Not Out Bug" bzres="INVALID"/>
<map bzstatus="RESOLVED" ttres="Not a Bug" bzres="INVALID"/>
<map bzstatus="RESOLVED" ttres="On Hold" bzres="LATER"/>
<map bzstatus="RESOLVED" ttres="Duplicate" bzres="DUPLICATE"/>
</xsl:template>


<xsl:template match="defect-status">
<xsl:comment>Stat: <xsl:value-of select="."/></xsl:comment>

<xsl:variable name="_maps">
<xsl:apply-templates select="." mode="resolution-map"/>
</xsl:variable>
<xsl:variable name="maps" select="exsl:node-set($_maps)/map"/>

<!-- Default resolution to "Code Change" if not present -->
<xsl:variable name="resolution">
<xsl:choose>
<xsl:when test="../fix-event/resolution">
<xsl:value-of select="../fix-event/resolution"/>
</xsl:when>
<xsl:otherwise>Code Change</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:comment>Reso: <xsl:value-of select="$resolution"/></xsl:comment>

<resolution>
<xsl:choose>
<xsl:when test="$maps">
<xsl:value-of select="$maps[@ttres = $resolution]/@bzres"/>
</xsl:when>
<xsl:otherwise>DEF_RES</xsl:otherwise>
</xsl:choose>
</resolution>

<bug_status>
<xsl:choose>
<xsl:when test="$maps">
<xsl:value-of select="$maps[@ttres = $resolution]/@bzstatus"/>
</xsl:when>
<xsl:otherwise>DEF_STATUS</xsl:otherwise>
</xsl:choose>
</bug_status>
</xsl:template>

<!-- SEVERITY - map TT.severity to BZ.severity -->
<xsl:template match="severity" mode="severity-map">
<map ttsev="Causes Crash" bzsev="critical"/>
<map ttsev="No Workaround" bzsev="major"/>
<map ttsev="Workaround" bzsev="minor"/>
<map ttsev="Cosmetic" bzsev="trivial"/>
</xsl:template>

<xsl:template match="severity">
<xsl:comment>Seve: <xsl:value-of select="."/></xsl:comment>

<xsl:variable name="_maps">
<xsl:apply-templates select="." mode="severity-map"/>
</xsl:variable>
<xsl:variable name="maps" select="exsl:node-set($_maps)/map"/>

<bug_severity>
<xsl:choose>
<xsl:when test="$maps">
<xsl:value-of select="$maps[@ttsev = current()/.]/@bzsev"/>
</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</bug_severity>
</xsl:template>

<!-- REPORTER - map TT.entered-by/last-name to bz.reporter -->
<xsl:template match="entered-by/last-name" mode="normalize">
<xsl:copy>
<xsl:apply-templates select="* | text()"/>
</xsl:copy>
<email-address>
<xsl:call-template name="getemail">
<xsl:with-param name="ln" select="."/>
</xsl:call-template>
</email-address>
</xsl:template>

<xsl:template match="entered-by/email-address">
<reporter><xsl:value-of select="."/></reporter>
</xsl:template>

<!-- CREATION_TS - map TT.date-entered to BZ.creation_ts -->
<!-- Note that we need to convert TT's MM/DD/YY format to BZ's YYYY-MM-DD HH:MM -->
<!-- We'll default the time to midnight - TT did not capture the time... -->
<xsl:template match="date-entered" mode="normalize">
<xsl:copy>
<xsl:apply-templates select="* | text()"/>
</xsl:copy>

<defect-date>
<xsl:call-template name="convdate">
<xsl:with-param name="date" select="."/>
</xsl:call-template>

</defect-date>
</xsl:template>

<xsl:template match="defect-date">
<creation_ts><xsl:value-of select="."/></creation_ts>
</xsl:template>

<!-- Description -->
<xsl:template match="reported-by-record/description">
<long_desc>
<who><xsl:value-of select="../../entered-by/email-address"/></who>
<bug_when>
<xsl:call-template name="convdate">
<xsl:with-param name="date" select="../date-found"/>
</xsl:call-template>
</bug_when>
<thetext><xsl:value-of select="."/></thetext>
</long_desc>
</xsl:template>

<!-- assigned-to -->
<!-- Grab value from currently-assigned-to.  If empty, grab last assigned-to -->
<xsl:template match="currently-assigned-to">
<xsl:variable name="curr-name" select="./last-name"/>
<xsl:variable name="ass-name" select="(parent::*/assign-event/assigned-to/last-name)[last()]"/>

<xsl:comment>Assi: "<xsl:value-of select="$curr-name"/>" or "<xsl:copy-of select="$ass-name"/>"</xsl:comment>

<xsl:variable name="curr-email">
<xsl:call-template name="getemail">
<xsl:with-param name="ln" select="$curr-name"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="email">
<xsl:choose>
<xsl:when test="contains($curr-email,'@')">
<xsl:value-of select="$curr-email"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getemail">
<xsl:with-param name="ln" select="$ass-name"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:variable name="final-email">
<xsl:choose>
<xsl:when test="contains($email,'@')">
<xsl:value-of select="$email"/>
</xsl:when>
<xsl:otherwise>default@domain.com</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<assigned_to><xsl:value-of select="$final-email"/></assigned_to>
</xsl:template>

<!-- date-last-modified -->
<xsl:template match="date-last-modified">
<delta_ts>
<xsl:call-template name="convdatetime">
<xsl:with-param name="datetime" select="."/>
</xsl:call-template>
</delta_ts>
</xsl:template>


<!-- Add any other notes.  Be sure to skip any notes with text -->
<!-- "This assignment was auto generated by TestTrack."        -->
<xsl:template match="notes">
<xsl:if test=". != 'This assignment was auto generated by TestTrack.'"> 
<long_desc>
<who>
<xsl:call-template name="getemail">
<xsl:with-param name="ln" select="../*/last-name"/>
</xsl:call-template>
</who>
<bug_when>
<xsl:call-template name="convdate">
<xsl:with-param name="date" select="../event-date"/>
</xsl:call-template>
</bug_when>
<thetext>
<xsl:value-of select="."/>
</thetext>
</long_desc>
</xsl:if> 
</xsl:template>

<!-- Incl. TT disposition and type in output for future ref -->
<xsl:template match="disposition">
<tt_disposition><xsl:value-of select="."/></tt_disposition>
</xsl:template>

<xsl:template match="type">
<tt_type><xsl:value-of select="."/></tt_type>
</xsl:template>

<!-- Throw away everything else... -->
<xsl:template match="*"></xsl:template>

<!-- Map last name to email address -->
<xsl:template name="getemail">
<xsl:param name="ln"/>

<xsl:variable name="email-addr">
<xsl:value-of select="$emailmaps[@ln = $ln]/@email"/>
</xsl:variable>

<xsl:value-of select="$email-addr"/>
</xsl:template>

<!-- Template for converting MM/DD/YY to YYYY-MM-DD HH:MM format -->
<xsl:template name="convdate">
<xsl:param name="date"/>

<xsl:variable name="date-nodes" select="str:tokenize($date, '/')"/>
<xsl:variable name="new-day" select="str:align($date-nodes[2], '00', 'right')"/>
<xsl:variable name="new-month" select="str:align($date-nodes[1], '00', 'right')"/>
<xsl:variable name="new-year" select="str:align($date-nodes[3], '2000', 'right')"/>
<xsl:value-of select="concat($new-year, '-', $new-month, '-', $new-day, ' ', '00:00')"/>
</xsl:template>

<!-- Template for converting MM/DD/YY HH:MM to YYYY-MM-DD HH:MM format -->
<xsl:template name="convdatetime">
<xsl:param name="datetime"/>

<xsl:variable name="datetime-nodes" select="str:tokenize($datetime, ' ')"/>
<xsl:variable name="date-portion" select="$datetime-nodes[1]"/>
<xsl:variable name="time-portion" select="$datetime-nodes[2]"/>
<xsl:variable name="ampm"         select="$datetime-nodes[3]"/>

<xsl:variable name="date-nodes" select="str:tokenize($date-portion, '/')"/>
<xsl:variable name="new-day" select="str:align($date-nodes[2], '00', 'right')"/>
<xsl:variable name="new-month" select="str:align($date-nodes[1], '00', 'right')"/>
<xsl:variable name="new-year" select="str:align($date-nodes[3], '2000', 'right')"/>

<xsl:variable name="time-nodes" select="str:tokenize($time-portion, ':')"/>
<xsl:variable name="hour" select="$time-nodes[1]"/>
<xsl:variable name="min" select="$time-nodes[2]"/>

<xsl:variable name="new-hour">
<xsl:choose>
<xsl:when test="$ampm='PM'">
<xsl:value-of select="$hour+12"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$hour"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:value-of select="concat($new-year, '-', $new-month, '-', $new-day, ' ', $new-hour, ':', $min)"/>

</xsl:template>

</xsl:stylesheet>

-- KevinJarnot - 12 Jul 2005
to top


You are here: Public > MigrateFromTestTrackProToBugzilla

to top

small<    [cached Nov 21 2008 at 17:29:17]>/small<-->

Copyright © 1999-2008 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Jarnot.com Wiki? Send feedback