Because tests are concrete things, writing them before turning to the design and implementation of the code forces developers to think in detail about what the requirements are, and makes it harder (though still possible) to gloss over any difficult or obscure issues. It does not, however, show you how those tests (requirements) can be satisfied - that requires thinking about algorithms. This may not be much of an issue when you are making incremental changes to an existing system, but it becomes more significant as the size, scope and novelty of the work increases, and especially when it is technically challenging, as in the case of concurrency or security, and when high performance and/or reliability matter.