So, you've read a book on TDD, a couple of blog posts from the gurus, and maybe even done the Calculator Kata several times. Now it's time to apply your knowledge to a Real Life Project that you are starting today. You probably stare at the empty solution and try to figure out where to start. "Create an instance of the System Under Test".. which system? "Mock or stub the dependencies".. which dependencies?
Let me give you a hand
Right now I'm also staring at the (almost) empty solution. I'll try to document what I think and do, and maybe you'll find it useful. However, remember that it's not the only way to do it, it's probably not the best way, and it even might be a bad way. But it works for me, and it might work for you, so, if you don't have a better solution, you might wanna try this one..
Meet Chpokk, an online .Net code editor.
Chpokk is meant as a lightweight replacement for Visual Studio, integrated with source control, plus some goodies like refactoring support, running your tests etc. I decided that today is a great day to develop the first feature that might be actually useful.
What do I want from my tests
There are several important requirements, that will help me a lot in writing my first test.
I want to produce some business value as soon as possible. I don't have time for all these funny AbstractFactoryFactory toys. If that means creating a one big static method, fine. I'll refactor it later. But when I refactor it, I need it to be covered with a test. So, my first test should be about the first useful thing I want to implement in my system.
I don't want my tests to be fragile. I don't know what my UI is going to be, and I don't know my API yet. But changing the UI can easily break many tests that depend on it, while the server side code can be easily refactored in sync with the tests. Not just UI, anything "stringy" should be kept out. For example, I don't want to hardcode the folder in which I'm going to keep the user's code files.
This requirement kind of contradicts the previous one, which suggested that my first test should cover everything. But while the first rquirement is more like a nice wish that would make me happy right now, the second one would save me from perpetual pain later, since robust tests are what makes me sleep well at night.
The tests should not use any knowledge from outside. This is better explained with an example. Say, I'm going to clone an existing repository from GitHub. Then I'm going to check if a certain file exists locally. The knowledge about the name of the file that should be there is not a part of the test. This can be a problem, since later looking at this test I won't know why it expects this particular file. In addition, I might rename this file later in order to use it in a different test.
How can I fix it? By adding this file to the remote repository as a part of the test. That makes my life harder, but at least I can look at the test and understand why the file should be there. In addition, my test is responsible for setting up its environment. Ideally, the test should have created a remote repository, of course, but that's probably too much. In fact, perhaps I could even manage without adding this file, but the repository content is a changing thing, while the repositories themselves tend to stay longer.
Enough philosophy, show me the code already!
Not so fassst, mah friend! Just wait for the next part, where I'm figuring the requirements for the first iteration and writing tests for them.