Prefere testar a interface durante o teste na implementação.
It's my understanding that private methods are untestable
Isso depende do seu ambiente de desenvolvimento, veja abaixo.
[private methods] shouldn't be worried about because the public API will provide enough information for verifying an object's integrity.
É isso mesmo, o TDD se concentra em testar a interface.
Métodos privados são um detalhe de implementação que pode mudar durante qualquer ciclo de re-fatoração. Deve ser possível refatorar sem alterar a interface ou o comportamento caixa preta . Na verdade, isso é parte do benefício do TDD, a facilidade com a qual você pode gerar a confiança de que alterações internas em uma classe não afetarão os usuários dessa classe.
Well, it's possible for me to make an object that has only private methods and interacts with other objects by listening to their events. This would be very encapsulated, but completely untestable.
Mesmo que a classe não tenha métodos públicos, os manipuladores de eventos são interface pública , e é contra essa interface pública que você pode testar.
Como os eventos são a interface, são os eventos que você precisará gerar para testar esse objeto.
Procure usar objetos simulados como a cola para o seu sistema de teste. Deve ser possível criar um objeto simulado simples que gere um evento e capte a mudança de estado resultante (possível por outro objeto simulado do receptor).
Also, it's considered bad practice to add methods for the sake of testing.
Absolutamente, você deve ser muito cauteloso em expor o estado interno.
Does this mean TDD is at odds with encapsulation? What is the appropriate balance?
Absolutamente não.
O TDD não deve alterar a implementação de suas aulas além de talvez simplificá-las (aplicando YAGNI de um ponto anterior).
A prática recomendada com o TDD é idêntica à prática recomendada sem o TDD. Você descobre o motivo, porque está usando a interface durante o desenvolvimento.
I'm inclined to make most or all of my methods public now...
Isso seria jogar o bebê com a água do banho.
Você não deve precisar para tornar todos os métodos públicos para que você possa desenvolver de forma TDD. Veja minhas anotações abaixo para ver se seus métodos privados realmente não podem ser testados.
Uma visão mais detalhada dos métodos privados de teste
Se você precisar testar algum comportamento particular de uma classe, dependendo do idioma / ambiente, você pode ter três opções:
- Coloque os testes na aula que você deseja testar.
- Coloque os testes em outra classe / arquivo de origem & expor os métodos privados que você deseja testar como métodos públicos.
- Use um ambiente de teste que permita manter separado o código de teste e produção e, ainda assim, permitir o acesso de código de teste a métodos privados do código de produção.
Obviamente, a terceira opção é de longe a melhor.
1) Coloque os testes na classe que você quer testar (não ideal)
Armazenar casos de teste na mesma classe / arquivo de origem que o código de produção sob teste é a opção mais simples. Mas sem muitas diretivas ou anotações pré-processador, você acabará com seu código de teste inchando seu código de produção desnecessariamente, e dependendo de como você estruturou seu código, você pode acabar expondo acidentalmente a implementação interna aos usuários daquele código. / p>
2) Exponha os métodos privados que você deseja testar como métodos públicos (realmente não é uma boa ideia)
Como sugerido, essa é uma prática muito ruim, destrói o encapsulamento e exporá a implementação interna aos usuários do código.
3) Use um ambiente de teste melhor (melhor opção, se estiver disponível)
No mundo do Eclipse, 3. pode ser alcançado usando fragmentos . No mundo C #, podemos usar classes parciais . Outros idiomas / ambientes geralmente têm funcionalidade semelhante, você só precisa encontrá-lo.
Assumindo cegamente 1. ou 2. as únicas opções provavelmente resultariam em software de produção inchado com código de teste ou interfaces de classe desagradáveis que lavam sua roupa suja em público. * 8 ')
- Ao todo - é muito melhor não testar a implementação privada.