Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a Season class. This Season has a few properties: among them, a list of Games. This should be populated from the same source that populated the rest of the Season properties.

I have a test to ensure all items in that list are of type Game.

There is no hard requirement that a Season must contain any Games, so testing that the list is not empty would not be entirely correct -- however, the test Season I'm using has plenty of games in it.

Writing "the minimum amount of code to make a test pass" is already done, because it is the empty list (so there are no not-Game objects).

What would be the fundamental TDD way to get the production code to parse+add games to the Season object?

Would the pragmatic way be to test via the size?


An alternative would be to generate the list of Games in my test, and see if Season.games == list_of_games

The problem with that is that there are a crapload of Foreign relations that will be going into those games, making the test code equivilant to the method that I'm testing -- which I don't think is the way it should work.

Or should I build them "by hand" from the test data -- instead of parsing it?

share|improve this question
    
What kinda of source are you loading them from? –  Winston Ewert May 12 '13 at 14:35
    
@WinstonEwert This is data returned from a REST API serving XML. I downloaded the Season endpoint locally to use as sample data. –  Travis May 12 '13 at 17:35
add comment

2 Answers

If I understand correctly, there is a requirement that states "a Season has a list of 0 or more Game objects. This list shall not contain objects of other types".

The easiest way to verify this requirement is via the method to add items to the list. You have a test to verify that it is possible to add Game objects to the list, and you have a second test to verify that adding non-Game objects fails.

(Exception: If you use a statically-type language, like C++, C# or Java, and you use the type system to ensure only Game objects can be added to the list, the second test is effectively performed by the compiler each time you write code to add an item to the list. There is no need then to write the test yourself.)

share|improve this answer
    
That's statically, not strongly typed. –  Winston Ewert May 12 '13 at 14:31
    
@WinstonEwert: corrected. –  Bart van Ingen Schenau May 12 '13 at 14:42
    
Other than at construction time, I do not plan on allowing items to be added to this list. This is for an API Wrapper so I'm mostly doing a 1:1 with some XML to custom objects. But I get where you're going. Maybe I'll add an addGame(x : Game) method, mock it out, and ensure it was called as many times as I expected. Do you think that is "testing" it enough, or am I mocking the piece that I'm testing? –  Travis May 12 '13 at 17:38
    
@Travis, what would that do that making an assertion on the length wouldn't do? –  Winston Ewert May 12 '13 at 19:42
    
@Travis: If your method to add an item to the list is the Season constructor, then just test that you can successfully construct a Season from an XML file that describes a single Game object and that if you try the same with an XML file that describes a non-Game object, you either get an empty list or an exception. –  Bart van Ingen Schenau May 13 '13 at 8:20
add comment

Extracting data from XML or JSON always seems a bit difficult to do in a TDD manner. You end up with a lot of code that looks like:

void parseElement(XMLElement element)
{
     name = element.getAttribute("name");
     home_team = teams.lookup( element.getAttribute("home") );
     away_team = teams.lookup( element.getAttribute("away") );
}

I can add assertions to check the name and teams, but it feels rather hard to justify. The code is so simple that attempting to verify that it actually works seems not worthwhile. Sure it makes sense to run the code and make sure it doesn't go up in flames, and it makes sense to check any non-trivial actions. But it is really worthwhile asserting each and every assignment? All you are really doing is redunandtly stating the same thing.

This is what I think you are hitting. Its a lot of work to verify that the deserialization was correct, but it doesn't really seem worthwhile. That's why you're hesitant to create a list of Games to test against. That's a lot of effort for little gain.

My solution is to devise a framework for extracting information, test that, and mostly trust that it works when applied to your objects. I don't know what language you are using, but here is a pythonish version.

class Season(XMLExtractable):
    XML_FIELDS = {
         'name' : AttributeGetter('name', str),
         'games' : ChildNodeGetter('game', Game),
         ...
    }

The XML_FIELDS dict tells me where each attribute should get its data. The objects constructed here have methods to fetch the value. I've tested all those objects, and I can mostly just trust that they work here. Basically, we move all the redundancy into data and operate on that data. We can test our operations on the data, but we'll assume the data is correct.

share|improve this answer
    
I disagree. If you're parsing the xml as you show, it is worthwhile to have tests, especially as the xml and resulting object graph get more complex. Only time I'd not really test is if the implementation used a built in xml serialized. –  Andy May 12 '13 at 20:25
    
@Andy, what exactly do you verify in this tests? Do your tests not just end up being almost duplicates of the code itself? –  Winston Ewert May 12 '13 at 21:08
    
The tests verify that object being hydrated from the xml is hydrated. The code does the assignment, the tests verify property values are as expected. –  Andy May 12 '13 at 21:12
    
@Andy, do you get a bunch of lines like: name = xml.getAttribute("name") which have parallel assertions in the test: assert foo.name == "foobar";? –  Winston Ewert May 12 '13 at 22:24
    
Yes.. how else can you be sure you parsed correctly? If in your code you put the element name as naem, hopefully you wouldn't repeat the mistake in your test assertion. –  Andy May 12 '13 at 22:46
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.