Skip to main content

The philosophy behind TDD



TDD is an art of developing quality software. So, I call TDD is an art. A professional programmer dreams to write a program which is bug free and easy to understand. A program that is appreciated by the co-developers. TDD is something that can help you to do that and van be more than that; it creates a culture of developing good software. To become TDDer needs experience and a creative mind. You have to be tester and also a pragmatic programmer. It leverages the essence of real world programming, the clean code approach and beauty of refactoring.  
Kent Beck in 2002 started this best practice and here I am trying to write some of my thoughts about it after experiencing this on my play projects,
Three golden rules of TDD:

  • 1.    You will start with a failing test. You are not supposed to write the production code until you have a failing test.

  • 2.    You will write sufficient code to pass this failing test but not anything more than that.

  • 3.    You will refactor the code you have just written when you have a green test for your code.

def TDD = [ RED, GREEN, REFRACTOR ]

TDD starts with a failing test. This test indicates that the feature is not implemented yet and you are going to add it to production code. Here on you will try to fix failing test just to make sure all your production code is covered with test. If the test passes before you've written or changed any code then clearly the test is not very effective, so write the test, ensure that it fails, and then write the code to satisfy the test.

Really, with TDD, each piece of code you write should be to fix a failing test. This way you ensure that your code is fully tested

When you start with a failing test, your mind starts thinking in different directions to pass this test. This is one step towards an evolving design. A failing test indicates there is something missing in the design and you should think about it and fix this. Also it generates a creative mind within you to come up with another set of test cases that can fail the piece of logic you have just written. The first failing test helps you to understand the input and output of the problem in an analytical way. You can have a green test first, but how would that help. This is really difficult to explain until you experience the essence of a failing test.

It is not so important that you should have an upfront design to start your TDD session, but yes you should have all acceptance criteria and scenarios ready. This will basically help you to come-up with different test cases and also to forecast your design. However try to scribble some design before you start the session, which is likely to change during refactoring. Design will evolve once you move ahead with your test cases and end of it you will have an elegant, simple and clean design which will be understandable to all. Try to defer decisions like, what database to be used, do we really need a database, do we really need a DI framework, do we need some ORM framework. Just try to defer these decisions as long as you can. One of the prime reasons to this is to keep you calm and focus on the work on hand. When you start thinking of a DI framework, it will start ruling your mind and your mind will be automatically motivated to think in that direction. Hence you will start shaping your design to fit the DI framework and it’s no more your design then; some framework has just made you to think in their way and once you introduced that there is no way you can come out of it. I believe this is wrong and we should trust our self while doing TDD, no external forces should rule your mind; however try to keep the design lean so that if required we can introduce them. Do not misunderstand me, I am not telling that we do not need a database or a framework that makes our life easy, what I am trying to say is take those decision late so that you can use your creative mind to come up with something better that that.     

Comments

Popular posts from this blog

Spring: Method Injection

This is useful when a Singleton bean need to use a non-singleton bean. Sometime your application may need to collaborate a prototype bean with a singleton bean to satisfy your business logic. That is your singleton bean is dependent on a prototype bean. Let’s consider three beans Customer Sales Person Product A customer may ask a sales Person to show different type of products from the repository. Let’s assume you have gone to a garment shop to buy a new shirt for the lucky date with your new girlfriend. So, it’s a tough choice and you may like to try different colors and styles and finally you will choose one. So, if we describe the above situation in the form of business logic inside one of your module, it will look like this, The sales Person should show a new product every time he requests. Let’s assume Customer and Sales Person to be singleton bean in your Spring container and Product as prototype. But based on bean life-cycle a prototype bean can not be injec...

Copying objects – Java Clonable interface

We can assign reference of an object to another, provided each of them satisfies an “ is-a” relationship or of same type. For example, a Dog object can hold the reference of another Dog object regardless both have different states. Similarly an Animal object can hold the reference of a Dog or Cat object, if they satisfies an “is-a” relationship. But hold on, these assignments do not help you to create a duplicate copy of the object. It’s nothing but different pointers pointing to the same memory location. Java provides API to clone an object. Using this API one can get a copy of an object to another. To achieve this, proposed class should implement Clonable interface (else JVM will throw CloneNotSupportedException during runtime). The rationale behind cloning is to get an independent copy of an object. The Object class has a clone() method which takes care of this operation. This method is protected by nature and returns an Object , when called.   You can call this ...

JUnit Rule : Creating Temporary Folder

I was surprised to see this beautiful feature in JUnit and it helped to ease to lots of constrains I face while writing JUnit tests. I basically follow TDD and as you guys know we focus more on writing tests, hence it is necessary to use some shortcuts availed by the tools like JUnit to make the process fast. Recently I had an issue where I had to create and delete a file before and after every test executes. I did that using @Before and @After annotation of Junit and it worked, however I was looking for more of a generic way to do this at one place. As I started googling I came across this post, which is amazing,  After reading the block I know how I can generalize my creating and deleting of a temporary file or folder (I decided to go with a temporary folder and a file inside it, which looks more readable and oganized). The JUnit class: public class TemporaryFolderTestCase { @Rule public TemporaryFolder temporaryFolder = new TemporaryF...