In my current project there's a reasonable development infrastructure. We use maven as our build tool and AnthillPro as continuous integration server. It supports integrating local changes of developers and makes sure all parts of the system work the way they should. By the way, this is my first time working with Anthill and I have to say I'm really disappointed. The only CI server that is probably worse is CruiseControl. I've used JetBrains's TeamCity on my previous project and it is way more sophisticated than AnthillPro, but I digress...
The problem that I faced concerning TDD and CI actually sounds very trivial: when should you check in code?
Let's say you are developing the TDD way. You think about the problem and come up with a neat JUnit test for your class, which by the way doesn't exist yet. The JUnit test makes a nice specification of what needs to be implemented. Unfortunately it's almost 5pm and you want to go home. The problem is that you will be out of office for the next couple of days. One of your peers will have to code the implementation, in order to keep the project going. So are you checking in your code?
The way a CI server usually works is that it checks your version control system every x minutes and gets the changes, triggers your configured build and runs your test cases. It can do a lot more, like fire up some server for integration testing or deploy your application to various test machines, running different operating system. In our case it checks SVN every hour, fetches the change-set and triggers the maven build. That comprises compiling, packaging and running instrumented JUnit tests. Only after each step was successful it shows the comforting green bar on the status page - and that's where the problem begins.
Since Anthill relies on maven to run the JUnit tests, you only see the green light when they all succeed. Maven simply indicates failures by returning -1. You can configure maven to ignore failing JUnit tests, which means it returns 0 and Anhill will show you the nice little green status bar. That's probably not really what continuous integration was introduced for, because you would have to dig into the log files to find out if all your JUnit tests really passed.
Let's get back to our example. Going down the TDD route all you have right now is a broken JUnit test, which surely makes a nice specification, but it doesn't satisfy your CI Server. If you check in your code you are gonna break the build. Basically your are left with the following options:
1. You don't check in your code. Instead you could e.g. email it to your fellow developers.
2. You quickly manage to extract the interface from the test case. Your peers could program against it.
3. You can configure maven to ignore your particular JUnit test. Therefore you'd have to adopt the POM file.
4. You comment out your JUnit annotations or the content of the test methods. That way the test wouldn't fail the build.
All of theses options are flawed not to say broken. The lesser evil would probably be a combination of option 1 and 2. Extract an interface that you can check in without breaking the build and email the JUnit test to your fellow developer to avoid him writing his own test case. It is not a very comforting solution, but I couldn't come up with anything better. Apparently, there is a discrepancy between CI and TDD or am I missing something?
You take the blue pill - the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill - you stay in Wonderland and I show you how deep the rabbit-hole goes.
Call me a green bar fetish, but I'm going for the blue pill. As I mentioned in the beginning the TDD approach in my opinion is kinda broken, for various reasons. I'm writing my JUnit tests after or sometimes even while I'm working on the implementation and I think that works quite well.