Test Driven Development

Test Driven Development

As of now Test-Driven Development (TDD) has become a mainstream for almost every language, tool, frontend/backend for the developers. TDD completely changed the outlook on software development. Developers stopped writing messy spaghetti code and writing better designed, more maintainable, clean code. Regression failures dropped drastically.

There are studies, papers, and discussions about how effective TDD is. Even though it is definitely useful to have some numbers, I don’t think they answer the question of What exactly is TDD is all about? Why should use TDD in the first place? The short answer is “because it is the simplest way to achieve both good quality code and good test coverage”. You might be wondering that some complex procedure that requires a lot of skill to implement TDD. Actually, test-driven development is very simple. The flowchart below shows the three steps in the process.

No alt text provided for this image

Red, Green and Refactor.

Red: The first step is to write a small unit test case on a behavior that we are about to implement. We may be having the requirements and the flow.

As we have only written the test and haven't written the implementation yet, this test will naturally fail. You have your first failing test. Normally, a failing test would be a cause for worry, but in this case, a failing test means that we're done with the first step of the process and can move on to the next step.

In this phase, you have to make decisions about how the code will be used. You base this on what you really need at the moment and not on what you think may be needed. Here comes another mistake: do not write a bunch of functions/ classes that you think you may need. Concentrate on the feature you are implementing and on what is really needed. Writing something the feature doesn’t require is over-engineering. In this phase, we learned that basically tests in TDD are nothing but executable requirements.

Green: In the first, we wrote a simple test that checked the behavior of the requirement that we are going to implement. Next, we write the code that implements the desired functionality. At this point, we aren't looking to create the best design or the most readable code. We just want something simple that will pass the test.

There are two reasons why a test might not pass: It might have failed or it might have caused an error. There is a small difference between these two. A failure indicates that we expected some outcome (usually via an assert), but got something else. 

For example, we are asserting that an object value is None. First the test will fail because the object does not exist. Suppose an object has some other value apart from None, then the test will fail. An error indicates that something unexpected happened, usually an unexpected exception was raised. In both the cases, the test does not pass, but for different reasons, and these are reported separately as test failures and test errors. Here we create an object and passes some value that is neither none nor negative.

No alt text provided for this image

This minimal implementation passes the test. As with the first bit of implementation, we aren't trying to implement the whole functionality. We want to implement just enough to make the test pass. Remember, when the test passes, it means the requirement is met.

Refactor: Refactor: Now that the test is passing, we go back and look at the code to see whether it can be improved. This may involve improving the design, or making it more readable or maintainable. We can use the tests written so far to ensure that we aren't breaking anything during the refactoring step.

At the beginning, since we tested for an object and its behavior we do not have anything to refactor, so let us move on to write another test.

No alt text provided for this image

In the red phase, we have to write a test on a behavior that you are about to implement. Yes, I wrote behavior. The word “test” in Test Driven Development is misleading. We should have called it “Behavioral Driven Development“ in the first place. Yes, I know, some people argue that BDD is different from TDD, but I don’t know if I agree. So in my opinion, BDD = TDD.

We have to write a test that uses a piece of code as if it were already implemented. Forget about the implementation! If, in this phase, we may be thinking about how you are going to write the production code, then we are doing it wrong! It is in this phase where we only concentrate on writing a clean interface for future users. This is the phase where we design how our code will be used by clients.

This first rule is the most important one and it is the rule that makes TDD different from regular testing. You write a test so that you can then write production code. You don’t write a test to test your code.

In the refactor phase, we are allowed to change the code, while keeping all tests green, so that it becomes better. What “better” means is up to the developer. But there is something mandatory: we have to remove code duplication. In this phase we play the part of a picky programmer who wants to fix/refactor the code to bring it to a professional level. In the red phase, we’re showing off our skills to our users. But in the refactor phase, we’re showing off our skills to the programmers who will read our implementation.

Removing code duplication often results in abstraction. A typical example is when we move two pieces of similar code into a helper class that works for both the functions/classes where the code has been removed. Just keep in mind that we cannot move to another test unless we’ve removed all the code duplication.

Conclusion

In this section I will try to answer to some common questions and misconceptions about Test Drive Development.

T.D.D. requires much more time than “normal” programming! What actually requires a lot of time is learning/mastering TDD as well as understanding how to set up and use a testing environment. When we are familiar with the testing tools and the TDD technique, it actually doesn’t require more time. On the contrary, it helps keep a project as simple as possible and thus saves time.

How many test do we have to write? The minimum amount that lets us write all the production code. The minimum amount, because every test slows down refactoring (when we change production code, we have to fix all the failing tests). On the other hand, refactoring is much simpler and safer on code under tests.

With Test Driven Development we don’t need to spend time on analysis and on designing the architecture. This cannot be more false. If what you are going to implement is not well-designed, at a certain point you will think “Ouch! I didn’t consider...”. And this means that you will have to delete production and test code. It is true that TDD helps with the “Just enough, just in time” recommendation of agile techniques, but it is definitely nota substitution for the analysis/design phase.

Test-driven development is an integral technique for achieving high quality and is part of everyday practice of most software developers today. However, it is still a challenging discipline that takes time and practice to master. We also need to pay attention to best practices and be very disciplined, otherwise you risk wasting time and not getting the expected benefits.

Additionally, in order to be effectively applied, writing test code needs to be explicitly considered as design tool, and not just as verification mechanism. Finally, this practice can only complement other design activities, not replace it. TDD will be an essential skill in the near future and want to get up to speed on it. 

要查看或添加评论,请登录

Syed Habeeb Ullah Quadri的更多文章

  • From AI to AI Agents: A New Frontier in Machine Intelligence

    From AI to AI Agents: A New Frontier in Machine Intelligence

    The field of artificial intelligence (AI) is rapidly evolving, with advancements leading us from traditional AI models…

  • Father's day

    Father's day

    Belated Happy Father's Day to all who're having their father as I've forgotten to publish this earlier. And I request…

  • My First Experience where I got a title "Robot"

    My First Experience where I got a title "Robot"

    When first started career in 1993 joined a software development company "Al-Masar Computers" in Riyadh located at busy…

    1 条评论
  • Learning is a never ending journey of life.

    Learning is a never ending journey of life.

    Life begins with learning and ends with death. We all learn from our elders, teachers, stars, superiors, surroundings…

  • Hiring Chaos and corruption in India

    Hiring Chaos and corruption in India

    Talent shortage is a real issue in the current market. Almost three quarters (72.

社区洞察

其他会员也浏览了