The first step to automation is programming, and the first step to write good code, is to write the unit test first. TDD has been long preached and practiced by various programmers, and in many organizations. But what exactly is TDD, is it just a diagram of Pass, Fail and Refactor, as so many of us know or is it more than that?
Learning TDD is hard, because programming itself is hard. And the shift of the perspective to write a unit test to make the code fail I believe one of the toughest shift in perspective a developer goes through. And this shift is crucial not with the developer mindset in your team, but in the management as well. Martin Fowler, in this insightful article describes about it, and I thought sharing of link will be better than trying to use my words, so here it is – https://martinfowler.com/bliki/TestPyramid.html
Let us jump into solving one of the Code Kata exercises FizzBuzz, by applying TDD. So the idea of FizzBuzz is, if I say 1, you say 1, if I say 2, you say 2, if I say 3, you say Fizz, if I say 4, you say 4, if I say 5, you say Buzz, if I say 6 you say Fizz, and if I say 10 you say Buzz and just in case I say 15 you say
FizzBuzz and this continues. So let us say we need to write an application, a simple console app, where if I pass an array of numbers, I get back an array of strings implementing FizzBuzz
So if input is –[1,2,3,5,7,9, 3,15,18,21,30]
The output is-[1,2,Fizz,Buzz,7,F10,1izz,Buzz,13,FizzBuzz,Fizz,Fizz,FizzBuzz]
The technical stack – C# as programming language, xUnit nuget package, FluentAssertions nuget package.
- We first create a test class, with an empty method, and a code class with an empty method.
- We now write enough test code to test requirement 1, which is if we pass 1, we should get “1”
- We need to understand this test will fail, and it then we will write the minimum possible code lines to make the test pass.
Let us see the test code-
As expected we see an error, as FizzBuzzClass doesn’t exists and nor does the method process.
The dev code, written to make the error go away-
The above are the minimal number of code lines which we can write to make the error go away. Please note, we might be tempted to go ahead and implement the rest of the logic, but we need to hold our horses in here, learn to, and first and foremost write the FAILING TEST.
The above will fail, as we have not handled the condition, that if 3 is passed, we need to return Fizz. So we now take care of it by adding the lines as follows-
And in the same manner we will add for Buzz remember in test first and Fail it.
And as we see this fail, we will make the change in the code class to take care of this
After a few iterations and refactoring, our code will look like the following –
We now move onto the next part, where we would want to pass for an array of input numbers, to get the expected array of strings, so we right the test again, for it to fail
Failure message –
We fix it by adding enough code lines in the code class to allow the method to pass.
And now if we execute the tests, we will get what we wanted, Green, and we can continue the process of refactoring by adding more abstraction, removing duplicate code as we keep solving more and more requirements, or even write better code than shared in the above example.
The final solution and files are available on github link –https://github.com/AgileTestingAlliance/TDDFizzBuzz.git
There are significant advantages one starts noticing and is long preached and measured with TDD practice –
- Better code coverage
- Detailed Documentation
- Fewer bugs in production, its measured almost 40-80% of bug reduction is experienced
- Better communication across team, and to know more go ahead and read more on it.
Many articles and links helped me write it, the references are as follows –