One of the things I need to test for the next iteration of the project I am on is a CSV -> XML converter. It is believed (rightly I think) that the financial types providing us the information will be more comfortable in Excel producing a CSV than building a funky XML document. I ended up using Jython instead of CPython because I didn’t want to re-write the conversion routine so my testing rig is somewhere between unit testing and actual testing (which will have to be done through the actual web app).

Before I give the full annotated test script, here are something handy that was amazingly difficult to find online.

To print a JDOM Document (stored here as the variable JDOMDocument)

import org.jdom.output
outputter = org.jdom.output.XMLOutputter()
print outputter.outputString(JDOMDocument)

A few notes about the following test script

  • The structure might not make much sense. That is because it is part of an overall automation framework. One of these days I’ll clean up the common code and write about it.
  • I had to refer to the schema location as an http:// url. For some reason using file:/// would not find the schema. Not a biggie though as I always have Tomcat handy anyways.
  • I changed a couple path names to classes so as to not leak any unnecessary information
  • A bunch of the conversion and verification stuff will eventually move to the util module, it just makes sense to have them here while developing / blogging
import copy
import constants, util
import com.partner.product.csvtoxml, org.jdom.output, org.jdom.input, java.io

class test:
    def __init__(self):
        # default test result is always "fail"
        self.result = "fail"

    def run(self):
        # this will be a list of the rows in our csv that is going to be
        # converted to xml
        rows = []

        # puts the header names are the first row
        rows.append(util.get_csv_headers())

        # because we don't want to waste time setting all the values, even
        # if they are blank, this creates a dictionary with all fields and
        # their default values
        r1 = copy.copy(constants.csv_constants)

        # override the ones we care about in this context
        r1["Program_Key"] = "10000"
        r1["Program_Effective_Start_Date"] = "01/10/2007"
        r1["Program_Effective_End_Date"] = "01/31/2007"
        r1["Application_Type"] = "B"
        r1["Transaction_Type"] = "R"
        r1["English_Program_Name"] = "Jython"
        r1["Term_Min"] = "36"
        r1["Term_Max"] = "36"
        r1["Interest_Rate"] = "34.45"

        # add our overridden values as the next row of the csv file
        rows.append(util.row_from_dict(r1))

        # if you wanted, you could now create an r2, r3, rN following the
        # above steps

        # get our converter class
        c = com.partner.product.csvtoxml.CsvToXmlConverter("FSAG01", "\n".join(rows))

        # which returns a JDOM Document instance
        JDOMDocument = c.convert()

        # we need raw xml for schema verification
        outputter = org.jdom.output.XMLOutputter()
        xml = outputter.outputString(JDOMDocument)

        # create a SAXBuilder instance and tune it's behaviour
        sb = org.jdom.input.SAXBuilder("org.apache.xerces.parsers.SAXParser")
        sb.setFeature("http://apache.org/xml/features/validation/schema", 1)
        sb.setFeature("http://xml.org/sax/features/validation", 1)

        # the schemaLocation attribute is a hint, and since my machine is different I
        # override it
        sb.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
                       "http://company.org/schema.xsd http://localhost:8080/schemas/schema.xsd")

        # do the schema verification
        try:
            a = sb.build(java.io.StringReader(xml))
            # if no exception, then it was okay and we mark the test as passed
            self.result = "pass"
        except org.jdom.input.JDOMParseException:
            pass