Showing posts with label testability. Show all posts
Showing posts with label testability. Show all posts

Tuesday, November 3, 2009

More on Testable Code, and the Law of Demeter

I started looking at a simple enhancement task today. Like many simple sounding tasks, when you peer at the 
system and look at what is actually involved, there may be ugly parts. Especially in ensuring testability, as I am committed to unit testing this code.

In my quest to test more (and test FIRST), I looked at what would be required to add the functionality, and specifically, how to test what I was adding.

Here are the issues with testability and excuses I came up with:
  • No unit test exists for the immediate classes in question (shame on me - it's my code) 
  • The code has a GUI - this usually makes testing harder
  • Too many external dependencies!
  • I haven't tested this exact type of code before (aka: I don't know how)
Tonight I'm going to focus on the dependency issue.

Taking a look at my model, it already relied on more external objects than it needed to for the required functionality. The requested enhancement would (if the pattern continued) require further addition of some heavy weight dependencies. Bye bye testability!

Fortunately, I had both the testability presentations still in my mind, and a coworker who had already solved this problem.

The feature in question is for administering users in a system. Among the things being manipulated are name, manager, credential reset, licensed features, and now - a user's preferred currency code (at the end of the day - a String). Great - slap in a few getters and setters, and we're done! Well not quite - currency code lives on a currency unit which is supplied by a unit system, well, which comes from this other big thing. You get the point. If I was lazy, I'd just pass this big other thing to my model so it could do its job. I'm not going to be lazy - I'm going to pay attention to the Law of Demeter.

This model don't really care about the 'other big thing', or the 'unit system', or anything other than that being able to set a user's preferred currency to Australian Dollars, therefore they have no place in this particular model.

Instead of that, my model will take a data source that can give it valid currency codes and set a user's currency code. Just a simple interface with a couple of methods that will be easily mockable for testing. While I'm at it, I'm going to pull out the existing extra dependencies (there was fortunately just one) that weren't needed. Now my interface has four methods, and I don't need any hulking database-requiring objects to get my model moving. A little shuffling here and there, and very little additional code, and my model is now much more easily tested. Suddenly the "I don't know how to test this" feeling has weakened a bit now that my class is simpler.

I want to write further on my take on the Law of Demeter, but it's 11:45PM and I need to submit an entry daily so I'll have to wrap this up tomorrow.

Afterwards, I plan to cover making testing the GUI easier.

Sunday, November 1, 2009

Writing Testable Code

One of the things I struggle with sometimes is how to write testable code. Especially in an existing system that has lots of established code that is difficult to test. The code may have existing tests, but they are heavy, system tests not quick and speedy unit tests. Eventually, writing more tests in the same style just makes the builds take too long to run, and eventually that one new test may requires several minutes of waiting. Tests that make you wait are not productive, and should not be the norm.

This week I found not one, but two good presentations regarding testable code. Firstly (seen @ the UCOSP blog) was a link to the slides for a presentation done by Misko Hevery & Cory Smith at OOPSLA '09, entitled: "Tutorial: How to Write Hard to Test Code" (PDF Google Docs link). There are quite a few slides, and in addition to illustrating bad practices, there are plenty of examples of writing more testable code as well. Highly recommended, entertaining and educational slides.

The second is a project I already knew about, but never got around to trying. Guice. If you haven't used it (or another Dependency Injection library), I encourage you to watch the youtube video on the main Guice page. The presentation itself has general tips on writing more testable code, and towards the end gets into more advanced examples using Guice. The general principles apply whether or not you use it.

I'll post again with further thoughts once I've had a chance to play around with Guice.