DaveO
DaveO

Reputation: 151

How to test this code

I'm trying my hand at TDD and unit-testing, having never really done either seriously.

I have an XML file that's output from a program. I want to convert this to JSON. I found xmltodict so what I want to do is:

def to_json(filename):
    with open(filename) as f:
        xml_ = f.read()
        dict_ = xmltodict.parse(xml_)
        json_ = json.dumps(dict_)
    return json_

How would I test this? Should I split it into 3 functions and test each separately? Should I code "defensively" against a bad filename? What about errors thrown by the parse and dumps method?

Finally, are there good references/books/blog posts that talk about this type of thing? I understand I should be unit testing and really like the idea of TDD but in practice I have no idea what I'm doing.

Upvotes: 3

Views: 241

Answers (1)

alecxe
alecxe

Reputation: 473853

Here's my insight:

First of all, I'd separate "opening the file" logic from the actual converting step.

Then, basically you need to make sure that your function converts legal and correct xml and throws an exception if xml is invalid or broken.

Here's a simple example what you should have:

import json
import unittest
import xmltodict


def to_json(xml_):
    dict_ = xmltodict.parse(xml_)
    json_ = json.dumps(dict_)
    return json_


class TestToJson(unittest.TestCase):
    def test_good_xml(self):
        xml = """<?xml version="1.0"?>
                <catalog>
                   <book id="bk101">
                      <author>Gambardella, Matthew</author>
                      <title>XML Developer's Guide</title>
                   </book>
                   <book id="bk102">
                      <author>Ralls, Kim</author>
                      <title>Midnight Rain</title>
                   </book>
                </catalog>"""
        self.assertEquals(json.loads(to_json(xml)), {"catalog": {
        "book": [{"@id": "bk101", "author": "Gambardella, Matthew", "title": "XML Developer\'s Guide"},
                 {"@id": "bk102", "author": "Ralls, Kim", "title": "Midnight Rain"}]}})

    def test_bad_xml(self):
        xml = "<broken><broken"
        self.assertRaises(Exception, to_json, xml)


if __name__ == "__main__":
    unittest.main()

As far as you should test different valid and invalid xml strings, you can make use of an awesome ddt package that will multiply your test methods automagically for different inputs.

Additionally, you may want to test somewhat unachievable in real life situation where your xmltodict returns an invalid dict object. In that case, you need to mock xmltodict.parse function and change it's return_value.

Speaking about TDD. Your code is already written. TDD uses different approach where you write your tests first, then try to make them pass by writing the actual code. You should definitely try it - it has a lot of benefits.

Some resources:

Upvotes: 1

Related Questions