Criar um projeto de teste e escrever alguns métodos de teste é um tipo de TDD, mas, na minha experiência, não ajuda muito, a menos que você esteja trabalhando em uma biblioteca em que haja uma API conhecida e chamadas de método correspondam diretamente a algo esperado pelo usuário. . Você precisa apresentar a lista correta de testes e, para um aplicativo não trivial, isso pode ser realmente difícil de fazer.
Eu recomendo tentar o SpecFlow - ele mantém a definição de testes bem separados da implementação e a estrutura dos arquivos de recursos obriga a pensar sobre o que você está realmente testando.
Quando você define um recurso, basta escrever algo como
When a user is saved
Then the user should exist
Como você não está em um arquivo de código neste momento, não fica tentado a pensar em detalhes da implementação, como qual método é chamado para criar um usuário ou até em qual classe ele está implementado. Você pode usar tags para escolher diferentes implementações, portanto, nesse nível, não importa se "o usuário está salvo" significa uma chamada para CreateUser ou abrir um navegador e enviar um formulário.
Depois de definir os recursos, todos os testes são gerados e começarão a passar à medida que você implementa as definições de etapas e o código do aplicativo real sendo testado.
Para um aplicativo simples, você pode apenas criar os arquivos de recursos, mas para algo mais complexo, é útil reunir previamente uma especificação mais completa. Eu uso um aplicativo de mapeamento mental do iPad para isso, mas você pode usar qualquer ferramenta com a qual se sinta mais confortável.
Comece com uma lista de recursos de alto nível, como "Registro do usuário". Eles tendem a ser muito amplos para escrever testes diretamente, portanto, divida-os em sub-recursos que podem ser claramente definidos e geralmente mapeiam para uma ação específica do usuário, como "Salvar usuário" ou "Exibir usuário existente".
Cada uma dessas subfunções precisará de uma lista de cenários que, juntos, definam completamente se o recurso está ou não funcionando, como "Pode salvar um usuário válido" e "Não é possível salvar um usuário com nome de usuário duplicado".
À medida que você cria essa lista, geralmente fica claro onde a estrutura precisa ser ajustada - se você não conseguir realizar nenhum teste de cenário para um recurso ou acabar com muitos em um recurso, esse recurso provavelmente será definido em o nível errado e precisa ser dividido ou alterado.