The amazing adventures of Doug Hughes

Unit Testing Anybody?

So, here I am being the good developer and attempting to put together a series of unit tests for a project (the generic data validation engine is actually very close!). I have always appreciated the concept of unit testing and I have no problem doing it for simple little test cases. Where it always tends to get left by the road side is when I run into one of those more complex scenarios that does not fit the mold.

There was just such an occasion last week and I still have not found a way around it – at least one that I like. So, here is the scenario. I have an object whose init method accepts an optional path to an XML configuration file and if received, parses that configuration file into an internal data structure which is a fairly complex series of nested structures and arrays. All is well and good until I went to write a couple of unit tests for this …. I know I should have written them first, but at least they are being written!

The problem is, as part of this XML parsing/conversion process, the object in question is generating unique identifiers and inserting them into the data structure. These unique identifiers are UUIDs, so you can probably start to see the issue already. The way I was going about testing this piece functionality was to pass in an example XML file to the init method, capture the resulting data structure, and then compare it against a manually created data structure. However, as the conversion process generates unique identifiers on the fly, I can’t mimic those exact same identifiers in my manually created data structure and thus the test fails.

One suggestion I had was to rewrite the process of creating these identifiers so that if I passed in a test flag, then it would generate the identifier in a way that could be replicated. While this could work, the fact that I am having to go back and introduce more logic and bend my code just for testing purposes does not sound right.

So, before I toss unit testing aside once again, does anybody have any bright ideas on how you might test functionality like this?

Comments on: "Unit Testing Anybody?" (9)

  1. Brian Kotek said:

    Doug, can the test account for this by looping over the result and matching on everything except the UUID? In other words, you can assume that if you loop over the results and the actual data is all correct, then the test passes. Basically, ignore the UUIDs (or just check that the key or value is a UUID) and check everything else that you can.

    Like

  2. Brian Kotek said:

    Doug, can the test account for this by looping over the result and matching on everything except the UUID? In other words, you can assume that if you loop over the results and the actual data is all correct, then the test passes. Basically, ignore the UUIDs (or just check that the key or value is a UUID) and check everything else that you can.

    Like

  3. Brian Kotek said:

    Hmm the blog is throwing an error when I submit a comment, but the comment still goes through.

    Like

  4. Yeah, like brian says, I would just check to see that the id in question is a valid UUID. Since you dont really know what its supposed to be. Because in this case any UUID seems like it would be fine.

    Like

  5. Jeff Chastain said:

    This is Jeff by the way … we really need to make that a bit more obvious.

    I can follow checking that the UUID is just a valid UUID, but how would you go about writing the test or the assertions then? In the past, I have always written a single assertion per test …. assert A equals B. How would you take a fairly large data structure and perform assertions on pieces of it?

    Like

  6. Jeremy French said:

    Couldn’t you do something like this:

    Like

  7. Patrick McElhaney said:

    “One suggestion I had was to rewrite the process of creating these identifiers so that if I passed in a test flag, then it would generate the identifier in a way that could be replicated. While this could work, the fact that I am having to go back and introduce more logic and bend my code just for testing purposes does not sound right.”

    You’re almost there. You need two different strategies to generate IDs, the normal way, and the predictable way.

    The CFC you’re testing shouldn’t have to worry about how to the ID is generated. It should depend on another component, and (in CF framework parlance) have that dependency injected.

    What you need to do is create a UUIDGenerator CFC and pass that into your component. Then when you’re testing you can pass in a PredictableIDGenerator instead.

    That way you don’t have to worry about a flag or an if statement. There’s nothing to suggest you changed your code just for the sake of making it testable. You’re decoupling, as good developers do.

    —-

    The next step is to have your init() method accept the contents of the XML file (a string or a stream or node) rather than a path on the file system. That way your unit test can be self-contained and not depend on a static, external file.

    Like

  8. Patrick McElhaney said:

    You’re almost there. You need two different strategies to generate IDs, the normal way, and the predictable way.

    The CFC you’re testing shouldn’t have to worry about how to the ID is generated. It should depend on another component, and (in CF framework parlance) have that dependency injected.

    What you need to do is create a UUIDGenerator CFC and pass that into your component. Then when you’re testing you can pass in a PredictableIDGenerator instead.

    That way you don’t have to worry about a flag or an if statement. There’s nothing to suggest you changed your code just for the sake of making it testable. You’re decoupling, as good developers do.

    —-

    The next step is to have your init() method accept the contents of the XML file (a string or a stream or node) rather than a path on the file system. That way your unit test can be self-contained and not depend on a static, external file.

    Like

  9. Adam Crump said:

    Why do you need to check that it is a UUID? all you need to test is that it is of the required length. If you wanted to get really tricky you could assert that none of the ids generated match each other. While I understand the concept of creating a UUIDGenerator CFC, this seems to be a bit of overkill. The purpose of this function is to assign a unique id to the object. Then you need to assert that the id is indeed unique. So if you passed in some other cfc that created known ids, then you are not really testing that they are unique. So in my opion it comes down to what is it that you want to test. That it got some id, or that it got a unique id.

    Like

Comments are closed.

Tag Cloud