Showing posts with label anti-patterns. Show all posts
Showing posts with label anti-patterns. Show all posts

Friday, November 10, 2006

Mocking the Inspector

TDD Anti-Patterns "The Mockery - Sometimes mocking can be good, and handy. But sometimes developers can lose themselves and in their effort to mock out what isn’t being tested. In this case, a unit test contains so many mocks, stubs, and/or fakes that the system under test isn’t even being tested at all, instead data returned from mocks is what is being tested."

"The Inspector - A unit test that violates encapsulation in an effort to achieve 100% code coverage, but knows so much about what is going on in the object that any attempt to refactor will break the existing test and require any change to be reflected in the unit test."

Saturday, January 21, 2006

Mocking Correctly

A really great posting, "Best and Worst Practices for Mock Objects" lists a number of best practices for mocking.

  • "Be careful about mocking or stubbing any interface that is outside your own codebase. If you don’t truly understand the semantics and proper usage of an interface you don’t have any business mocking that interface in a unit test. My best advice is to create your own interface to wrap the interaction with the external API classes."
  • "My advice is to just test the data access code against the actual database with integration tests. For the most part I think testing persistence code without the database is a complete waste of time."
  • "I’ve worked with some people before that felt that there should never be more than 1-2 mock objects involved in any single unit test. I wouldn’t make a hard and fast rule on the limit, but anything more than 2 or 3 should probably make you question the design...Minimizing the number of mock objects necessary for any given unit test is a very effective way of keeping the Cyclomatic Complexity of your classes below an acceptable level."
  • "Ideally you only want to mock the dependencies of the class being tested, not the dependencies of the dependencies. From hurtful experience, deviating from this practice will create unit test code that is very tightly coupled to the internal implementation of a class’s dependencies."


A few more occurred to me:
  • Use as many patterns and idioms in your unit tests that you do in regular code, like testing exceptions and fixtures. This can be a great way to reduce the drudgery of testing bean objects for instance (not that I in anyway condone the use of bean objects).
  • Allow reuse of commonly used objects between tests.
  • The length and complexity of a unit tests is an indication of the complexity of the underlying object - once a test reaches a certain length/complexity it's time to refactor the object being tested.
  • Duplication in tests is just as bad as duplication in the code being tested.
  • No code goes into production just for the sake of testing.
  • Use reflection to gain access to internal object state. This is related to the previous point as a way to avoid artifacts of testing in production code. Other ideas include a good equals method, package level access and getter methods - but these leave code that may only exist for testing. And the last two are also a good way to break encapsulation.
  • Something that is easy to test is not always good design. For instance, having a fixture or utility code that makes bean objects easy to test drive shouldn't dictate using bean objects for everything.


The previous post in the series, "Why and When to Use Mock Objects" lists what makes a good unit test including: being atomic, order independent and isolated, intention revealing, easy to setup (a unit test code smell is a lot of setup code) and runs fast.

There also looks like a really interesting site, Test Automation Patterns. It lists test code smells including: test code duplication is bad, obscure tests, and data sensitivity. Also, a list of fixture strategies: standard, fresh and shared.

Friday, January 13, 2006

Don't put all your Pasta in the One Basket

What Sort of Pasta Do You Want? "After reflecting on a system that was developed using techniques found more so in agilest development teams such as Test Driven Development (TDD) and dependency injection, they observed that the parts of the system were more loosely coupled and more easily interchangeable, good indicators that it would be a better system to maintain. The code is better described as ravioli code instead of that of its more common pasta brethren.

This analogy has really stuck with me since because of the number of parallels it draws. Take one such example – the reason that ravioli is typically more expensive than spaghetti, even though they are both made from the same fundamental ingredients, is that making good ravioli takes a lot more skill than it does spaghetti. This idea is,of course, not new, and can be taken to extremes (see Wikipedia’s entry) but I know which one is is my favourite."

So ravioli code is part of the pasta theory of programming which includes lasagne code.

A little bit of Spring, makes your code Sing! "We make extensive use of Spring at the day job, and feel it has been a key contributor to our extremely high code coverage, and the promotion of the ravioli code pattern; although some are of the opinion that ravioli code is an anti-pattern, I prefer smaller pieces loosely joined over the alternative."

It is an anti-pattern in the way that too many, loosely joined, tiny pieces of code hampers the understanding of the code. Too many classes with 10 lines in them calling another class, just catching an exception or looping around a method call, etc. In this way, it can reduce the ease at which code can be modified.

In "Where Smalltalk Went Wrong 2": "Again, ravioli code doesn't offer a path from here to there. "Here" in this case is the ignorant programmer first introduced to the code, "there" is the same programmer successfully making whatever change they need to make. In my experience with ravioli code there is a gestalt which is arrived at in a sudden realization, when the picture comes together. But before you reach that realization you find yourself in a murky set of code where it is difficult to predict effects or determine causality, and you seldom know how far away you are from the gestalt realization.".

To push the analogy, the ravoli becomes too small so that there is nothing left but empty shells of pasta. It's much more palatable, code-wise, than spaghetti (where the goodness is all over the plate and can't be stuffed in) or mud.

In the same way that there is duplication detection there should also be a metric available to judge whether a piece of code is not providing enough functionality or value. However, the way most code is written this isn't frequently a problem. A good example given of "about the right size" is where the algorithm is on paper and the code is in our head.

Monday, July 18, 2005

Pasta Preference

Ravioli code "The opposite of spaghetti code, where too many small objects that rely on many other small objects are created."

See also spaghetti code.