Test Driven Development: Best Practices and Benefits

Introduction

There are a lot of software development methodologies, and software QA plays a crucial role in ensuring their effectiveness. The most popular approaches of the present day are Iterative and Agile. But there are also techniques that are rarely used in their entirety, though developers make use of some of the advantages from them in the development process. I think the most well-known is Test Driven Development (TDD, in what follows).

Testing is a necessary step during software development. Test teams use automated software testing and manual testing services to test user interfaces, the business logic of the application, and sometimes parts of the API, using test scripts or applications. However, they are unable to fully test the program modules and the source code in general. This task is usually handled by developers who debug the code and create test applications to evaluate certain parts of it. Today, these traditional testing methods are becoming outdated. It is now more efficient to write Unit tests (small tests that focus on individual methods or code segments). There are many Unit test frameworks for various programming languages, ranging from widely used ones like .Net (NUnit, MsTest) and Java (Jtest, Junit) to less common ones such as Fortran (Funit) or Haskell (Hunit). In this article, all examples will focus on Microsoft .Net, as the most extensive experience in Unit Testing is with C# .Net development.

 

the relation between TDD and Unit testing

But what is the relation between TDD and Unit testing? The answer is the following, TDD is a development methodology based on Unit Testing. After creating an application architecture, after designing all the modules and classes, a developer creates a separate unit test project (the better practice is creating an individual test project for each module) and writes a test method for each logical part of the planned source code. Usually, this means the creation of test methods for each method (for example database layer: for all the entities to create, update and delete them) or for the business logic workflows like making a credit card payment or post the order to the tracking system. The main target is to cover the whole source code by unit tests so that all the code will be tested during test running. There are special tools to calculate the Unit test coverage in the project. For the MS .Net and .NUnit framework, such a tool is NCover. It runs all the unit tests, and checks which parts of the code are covered (it could check if if-construction and switch-construction cover all conditions).

 

WRITE THE TEST BEFORE THE CODE IS WRITTEN

 

However, this tool could only be run after the source code is written. At the first step, we only have the skeleton structure of the application project and the unit testing project with the complete list of implemented unit tests for all the test cases. “WRITE THE TEST BEFORE THE CODE IS WRITTEN” is the main idea of the TDD and it could make almost all the developers go crazy. So that’s why TDD is so rarely fully used in the development cycle; it’s very difficult to predict what logic should be tested in future code. The easiest part, where the TDD could be fully used, is Database Layer. But there is also one issue: Unit tests must not relate to external resources like the Database or internet connection. Because if it relates, the problem with the external resource (like the slow internet connection) could fail the test and we won’t know the real source of the test issue. So for the Database testing, a detached database is created. In .Net MS SQL projects developers usually create a database structure in an MDF file and attach this file during the testing project, as if it is a real database hosted on the MS SQL SERVER. There should be no difference in db connection for the application in such a case. But for different parts of the code, there are unmanaged resources that could not be detached, like Web services. On the one hand, we could not communicate to the real web service during Unit Testing, on the other hand, we could not “detach” the web service. So we should somehow emulate the work of the web service. There is a special term like the “mock” object for an object which simulates the work of a real object. And there are frameworks to work with such mocks. For .Net NUNit such framework is NMock. I could tell you more about the mocks and the method of changing the real object to the fake ones, and I intend to do this in a separate detailed article.

Stories from real life

I think this is enough theory for now and you probably want to know more about my experience of using the TDD on real projects.
I was involved in writing unit tests for many projects. But only two of them had something that was looking like real TDD.

One of them was a very powerful and scalable Web Based ERP System, designed using the MVC pattern. And the architect of the project (also the tech lead) decided to try the TDD methodology from the beginning. I was involved in Database layer design, so I started the development by creating dummy tests for every entity in the database model. Three tests for each: Select, Update, and Delete tests. In the future additional tests were added for the methods with filter expressions. And I want to say that the complete coverage of the Database layer by the unit tests helped us a lot. It was very easy to track changes in the database. If something was changed (deleted of the added column, or renamed fields) the test just failed. And the developers’ team knew that some additional update scripts for the database should be written so the database created from the initial script could work with the existing code.

For that project, the services layer and the controller layer were covered by the tests and the coverage was almost 100%. For sure it was not the ideal TDD, because a bigger part of the tests was written only after the code was stable. But anyway it was the first and unforgettable experience in writing code that will be automatically tested on a regular rational basis.

On the second project, the situation was almost the same. The only difference was that the tests were not written from the beginning. But after several years, when the project was already in production, the customer changed their representative to an ex-developer. And he suggested to us an idea of the Unit tests Coverage creation, and after a few months the coverage was more than 50%. We also adopted the requirement to add the HTML version of NCover report to every build that was planned for release.

scalable Web Based ERP System
scalable Web Based ERP System 2

 

During these two projects, the automatic Unit tests running was configured on the build server and was triggered on every source code commit. So if a developer had committed the code that didn’t work the whole team received the red “panic” mail alert with the build breaker name. So he immediately started to find the problem source to make the fix and commit it, to keep the version on the source control stable.

Conclusion

After all this detailed information and stories from the real-life I want to make a little summary.
So what are the advantages of the TDD?

  • We tested all the parts of the code before releasing the build (every developer could run the unit test, when he or she wants on his or her own computer, to know if the code still works)
  • We integrated unit tests on the build server to know if the code is working on each build
  • We knew who made a bug at the time of the source control commit when the unit test run was triggered to run in each case

So we will have guarantees that all the code is working in case of 100% unit test coverage. This is an optimistic scenario, and the application could have defects even if the unit test check is passed successfully. For example, if a unit test has a bug in it, or developer changes code logic but didn’t change the unit tests. Unit tests should be kept in the actual state or they will just cause problems and frustration during test execution. But even partial use of TDD for development projects could decrease the quantity of the defects by several times. And developers will have much less headache from bug fixing. So I advise every developer to use the TDD and Unit Testing if they have such possibilities and for all projects starting from tiny to the major ones. And you will not regret the time you spent on unit test development, because they will bring a powerful instrument of code testing, that will increase the quality of your project and save a lot of effort in the future.

Contact Us
Contact Us


    Insert math as
    Block
    Inline
    Additional settings
    Formula color
    Text color
    #333333
    Type math using LaTeX
    Preview
    \({}\)
    Nothing to preview
    Insert