This is a buzz word in development for some time. TDD got into picture when Agile storm hit the software development industry even though they don't have much relation. Let's look at what is mean by TDD ie Test Driven Development.
As the meaning says the software development process is driven by test in a TDD environment. Developers need to write automated test case first which will fail obviously. Then write code to make that test passing. When we say automated test case, its again a program which is calling the code / function intended to develop to fulfill the requirements.
Once one test passes, developer needs to think about next scenario and writes test for that scenario. First it will fail, then we will change the production code to pass that test. Finally we will be ending in a scenario where there will be many test cases / test function for one production function. The idea is whatever the developer thinks, it needs to be recorded in the form of test cases. In other words even if, there is not much documentation, by looking at the tests new developers should be able to understand the intentions of particular function.
After all the test cases are completed, the production code needs to be re-factored to standards. Use of proper patterns, making sure its adhering to SOLID principles are coming in this phase. Normally delivery oriented companies or companies want to make more profits and budget constraint projects never go for this step. If they do so it will surely byte them back in future during maintenance phase of the project.
We talked about writing tests, what is the type of test case or what do they test? Is it load test, functionality test or integration tests? Can we get rid of QA department if we bring TDD methodology?
Never. In TDD we are writing unit tests only. Developer tests his own API to make sure that, his piece of code / function will work as expected in all the scenarios. Other type of test such as functionality testing, integration testing & load testing needs to be carried by the QA / Testing department.
Unit as the name says testing small units of program. In most of the programming languages today, the smallest unit of program which can be tested is function / method. So we are testing functions via unit testing. We can say its part of API testing as well. But its not full API Testing. API Testing includes more factors.
Important thing to remember here is, unit test is to test one single unit. Not its upstream or downstream dependencies.
Why this is more important? If we take any layered application, the business logic is supposed to be in single layer which we normally call as business access layer. Business logic is nothing but collection of if...else and looping code based on client's requirements. So the unit testing is more applicable on business layer. If we take data access layer, there are not much code expected other than the database interactions and those are pretty static in all the projects. So lets take one scenario to get the idea clear.
Unit testing in real scenario
Suppose, we are developing an address book application. We need to validate names for special characters & validate the Zip code (Pincode / postal code in India) whether its real or not.That validation logic obviously comes in business layer. (Of course UI will have validation but its optional. BL can never avoid it)
In this situation, when we write the test method for BL.InsertPerson(Person p), we will be obviously calling a web service which will return true / false for a given zip code. During development time we will be running the tests so many times and if we try to call that web service all the times, it will take us precious time. So what to do?
Answer is Mock object. In an ideal case, if we are following SOLID principles, there would be an IZipcodeValidator interface with Validate() method. Mock this interface and return true always. So that we can unit test the InsertPerson() method. Then what about the data access layer. The default data access layer will obviously call database and try to save the data in it. But do we really need the database interaction when developing the business layer?
No. Remember we are unit testing single unit of code not its dependencies such as data access or zip code validator. The aim of the unit tests in this case is to make sure
- If the parameters into BL.InsertPerson is wrong ensure there is exception
- If the parameters are valid, make sure the IDataAccess.Insert() is called.
- More test scenarios like,
- If the data access throws exception BL.InsertPerson should not eat it
- More (as of me it goes to infinity:))
If we are not calling the real data access, how do we make sure the business layer function is working proper. As we saw above,its the magic of mock object. It knows what to do for particular scenario. How do we create mock objects? Do we need to write mock classes?
Wiki says "Mock objects are simulated objects that mimic the behavior or real objects in controlled ways". What does it mean? We are creating some dummy objects (simulated) which can be injected as dependency in the class under test (mimic the behavior). Important thing to remember is without knowledge in dependency injects its very difficult to adopt the TDD concept. The methods in those mock objects will return the value to suit to the test case (controlled ways). There are 2 ways to create mock objects.
Hand coded mocks / fakes
Here we just implement the same interface into one more class and return values appropriately for different test cases. If different test cases needs the behavior in different manner we need to create many fake classes. This is not practical at all.
Mock objects using framework
The mocking framework / library can be just another .Net / Java library which can create the mock object for us. We can ask the library "get me mock object for my interface". Then we can set rules on that returned object on how to behave when particular method is called or event fired ets... Once the mock object is set it can be injected into the code which we are testing.
I know its very hard to explain by writing. So it would be better, if we can spend some time on youtube which explains how it can be done in real life.
Comparing mocking frameworks
We discussed about mocking library. Are there many libraries? If so which library is the best? I still didn't get the answer. We have started using Moq library to evaluate it. There are many comparisons in internet. Unfortunately none of them are recommending one library. As of my experiment with Moq, I will suggest that for simple projects. The main reason is that, Moq is the one most of the fellow developers are using :)
Links to mocking library comparisonshttp://www.slideshare.net/dhelper/battle-of-the-mocking-frameworks
There are more concepts in unit testing such as stubbing and faking. All are related but slightly different.