Test Driven Development — To be or Not to be?
By: Ujjwal Bagwe
Tags: Development, Testing, Coding, Software Development, Tdd

“Does it work?” most dreaded question every developer hears whenever he or she makes changes anything or adds a bit to the existing code.

“hope so” the usual response we give with hope that our efforts have the right result.

But we can strive for Better.

Software is a non-linear system. A single change in front of you can break and adversely affect somewhere.

E.g. One incorrect data format can adversely affect different parts of the system. (y2k Problem).

When disparate parts of systems start failing it brings frustration, pain, and embarrassment. When applications fail the whole world knows about it & people will tweet about it.

we should quickly know if the code that worked before continues to work.

And because of this, we need rapid, compact and automated feedback loops. With automated tests, we can fail fast, fix fast and deploy the resilient-robust application in production that works smoothly.

Automated test cases have a deep impact on the design of code. It usually forces the code to be modular, highly cohesive and loosely coupled. Which in return gives you a way to modify your code easily that eventually has a positive impact on the cost of change.

What makes this process challenging?

Code gets modified several times in its life and if it is not getting modified then applications must be dead. Projects get evolved by adding new features, UX/UI enhancement and fixing bugs and all this change cycle cost to your organization. Therefore changes should

Be easily doable, affordable and cost-effective. have the right effect.

Can we Minimise the cost of change?

Yes, we can, if the design is flexible, extendable and maintainable. Test-driven development can help us with that. If our craft follows the design practices of high cohesion, loose coupling, the right level of abstractions and on the top, if tests provide us the feedback which boosts our confidence then changes become affordable.

Does it mean no QA?

it's not about manual vs automation. It's about having the right balance of both by putting them at the right place for work.

Testing vs. Verification

Let me give you our example.

Whenever we are trying to release a new application or revamp an existing one, our manager makes sure that he manually exercises application. His intention behind the action is to get insights. How will the user feel? Is it usable? Can we optimize our workflow by removing a few steps? That gives him an idea about the capabilities and limitation of applications. I hope this gives you clarity about Testing.

Verification on the other side gives you confirmation status. Are your calculations right? Does your code do what it's intended to?

You might have seen that people calling both of these actions with a single name as Testing. But in the literature of software testing both the words have different actions attached to it.

Verification answers the question, “Did we build the right system?” While Testing addresses, “Did we build the system right?”

In my journey of software development, I have observed different models that have been adopted for automated verification.

No automation, only manual verification: We were literally struggling to validate application after a change and sacrificing our pleasant nights. Automation up to certain level done by another team: As this team focuses on UI level handling that keeps on adding efforts for both teams in order to support the support tools(Test tools). Keep on waiting for the test hooks at each layer so that they can test it. Automation at the right level: This model has shown me what maturity of testing is by putting efforts at each level.

Make sure that your adoption for automation does not create ice cream cone anti-pattern. One should think before adopting the ice cream cone anti-pattern, Because of the following reasons:

As UI is fluid it keeps on changing as code on its depends changes. Making both of this synchronized consumes more time. Time-consuming as this test runs, whole application has been bootstrapped with all services, databases, it takes time to run which makes the process slower. These tests are not descriptive and precise it will only tell you something has failed but won't tell you what and where failed. It doesn't stop anyone from putting logic into UI which eventually sacrifices the code modularity.

Here is one nice article by Martin Flower on test pyramid.

Still it is not testable?

when we are saying that code is not testable it will be only because of

Lack in design. We don't know how our code works.

Let's see what design principles mean:

Highly cohesive: If code or method to be tested does lots of work then it has low cohesion. Break that piece of code to the extent that no test can be written now. In this way, we can make the code highly cohesive.

Loosely Coupled: Is service or dependencies have been directly wired up into our code then it has tight coupling. Find out the way by which we can inject the service or dependencies into code which gives us more flexibility to change the services or dependencies as an when required without touching the consumer's codebase.

Levels of Abstraction: Put your efforts in understanding the internal working of your library or framework. We need to figure it out how different parts of software stitch together in order to give the functionality we are looking for.

Desire to learn: don't confuse yourself by lack of knowledge or skill by impossibility and complexity. Things which we find complex are might because of our familiarity construct of language. Skills and knowledge can be developed by learning from others.

Having said that it needs consistency, discipline & efforts to learn for adopting this programming approach. Now you decide whether you want to start with TDD and not.