matanc1
matanc1

Reputation: 7033

How to write a unit test for an XML parser I wrote in Java

The context is as follows:

I've got objects that represent Tweets (from Twitter). Each object has an id, a date and the id of the original tweet (if there was one).

I receive a file of tweets (where each tweet is in the format of 05/04/2014 12:00:00, tweetID, originalID and is in its' own line) and I want to save them as an XML file where each field has its' own tag.

I want to then be able to read the file and return a list of Tweet objects corresponding to the Tweets from the XML file.

After writing the XML parser that does this I want to test that it works correctly. I've got no idea how to test this.

The XML Parser:

public class TweetToXMLConverter implements TweetImporterExporter {
    //there is a single file used for the tweets database
    static final String xmlPath = "src/main/resources/tweetsDataBase.xml";
    //some "defines", as we like to call them ;)
    static final String DB_HEADER = "tweetDataBase";
    static final String TWEET_HEADER = "tweet";
    static final String TWEET_ID_FIELD = "id";
    static final String TWEET_ORIGIN_ID_FIELD = "original tweet";
    static final String TWEET_DATE_FIELD = "tweet date";
    static File xmlFile;
    static boolean initialized = false;

    @Override
    public void createDB() {
        try {
            Element tweetDB = new Element(DB_HEADER);
            Document doc = new Document(tweetDB);
            doc.setRootElement(tweetDB);

            XMLOutputter xmlOutput = new XMLOutputter();

            // display nice nice? WTF does that chinese whacko want?
            xmlOutput.setFormat(Format.getPrettyFormat());
            xmlOutput.output(doc, new FileWriter(xmlPath));
            xmlFile = new File(xmlPath);
            initialized = true;

        } catch (IOException io) {
            System.out.println(io.getMessage());
        }
    }

    @Override
    public void addTweet(Tweet tweet) {
        if (!initialized) {
            //TODO throw an exception? should not come to pass!
            return;
        }
        SAXBuilder builder = new SAXBuilder();
        try {
            Document document = (Document) builder.build(xmlFile);

            Element newTweet = new Element(TWEET_HEADER);
            newTweet.setAttribute(new Attribute(TWEET_ID_FIELD, tweet.getTweetID()));
            newTweet.setAttribute(new Attribute(TWEET_DATE_FIELD, tweet.getDate().toString()));
            if (tweet.isRetweet())
                newTweet.addContent(new Element(TWEET_ORIGIN_ID_FIELD).setText(tweet.getOriginalTweet()));

            document.getRootElement().addContent(newTweet);

        } catch (IOException io) {
            System.out.println(io.getMessage());
        } catch (JDOMException jdomex) {
            System.out.println(jdomex.getMessage());
        }
    }

    //break glass in case of emergency
    @Override
    public void addListOfTweets(List<Tweet> list) {
        for (Tweet t : list) {
            addTweet(t);
        }
    }

    @Override
    public List<Tweet> getListOfTweets() {
        if (!initialized) {
            //TODO throw an exception? should not come to pass!
            return null;
        }
        try {
            SAXBuilder builder = new SAXBuilder();
            Document document;
            document = (Document) builder.build(xmlFile);

            List<Tweet> $ = new ArrayList<Tweet>();
            for (Object o : document.getRootElement().getChildren(TWEET_HEADER)) {
                Element rawTweet = (Element) o;

                String id = rawTweet.getAttributeValue(TWEET_ID_FIELD);
                String original = rawTweet.getChildText(TWEET_ORIGIN_ID_FIELD);
                Date date = new Date(rawTweet.getAttributeValue(TWEET_DATE_FIELD));
                $.add(new Tweet(id, original, date));
            }
            return $;
        } catch (JDOMException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

Some usage:

private TweetImporterExporter converter;
List<Tweet> tweetList = converter.getListOfTweets();
for (String tweetString : lines)
    converter.addTweet(new Tweet(tweetString));

How can I make sure the the XML file I read (that contains tweets) corresponds to the file I receive (in the form stated above)?

How can I make sure the tweets I add to the file correspond to the ones I tried to add?

Upvotes: 1

Views: 8197

Answers (1)

Gabriel Ruiu
Gabriel Ruiu

Reputation: 2803

Assuming that you have the following model:

public class Tweet {

    private Long id;
    private Date date;
    private Long originalTweetid;
    //getters and seters
} 

The process would be the following:

  • create an isntance of TweetToXMLConverter
  • create a list of Tweet instances that you expect to receive after parsing the file
  • feed the converter the list you generated
  • compare the list received by parsing the list and the list you initiated at the start of the test

    public class MainTest {
    
        private TweetToXMLConverter converter;
        private List<Tweet> tweets;
    
        @Before
        public void setup() {
    
            Tweet tweet = new Tweet(1, "05/04/2014 12:00:00", 2);
            Tweet tweet2 = new Tweet(2, "06/04/2014 12:00:00", 1);
            Tweet tweet3 = new Tweet(3, "07/04/2014 12:00:00", 2);
            tweets.add(tweet);
            tweets.add(tweet2);
            tweets.add(tweet3);
    
            converter = new TweetToXMLConverter();
            converter.addListOfTweets(tweets);
        }
    
        @Test
        public void testParse() {
    
            List<Tweet> parsedTweets = converter.getListOfTweets();
            Assert.assertEquals(parsedTweets.size(), tweets.size());
            for (int i=0; i<parsedTweets.size(); i++) {
                //assuming that both lists are sorted
                Assert.assertEquals(parsedTweets.get(i), tweets.get(i)); 
            };
        }
    }
    

I am using JUnit for the actual testing.

Upvotes: 2

Related Questions