Essa é uma discussão frequente, que inclusive apareceu recentemente no .NET Architects: devo ou não devo testar métodos privados? Minha opinião é que não, você nunca precisa testar métodos privados!

Se você está escrevendo testes para uma classe, e sente a necessidade de testar um determinado método privado de maneira isolada, isso é bom: você está recebendo feedback do seu teste em relação ao seu design! Afinal, não é isso que todos dizem sobre TDD?

E o que o teste está dizendo? Ele está te dizendo que sua classe não está coesa. Quando uma classe não é coesa, ou seja, ela tem mais do que uma responsabilidade (ela faz coisas demais!), geralmente existem um conjunto de métodos nela que são responsáveis por uma das responsabilidades, e um outro conjunto de métodos responsáveis pela outra responsabilidade.

Uma situação real: O programador criou uma classe para lidar com uma funcionalidade específica, e para isso criou um método público. A outra necessidade surgiu com o passar do tempo (às vezes nem tanto tempo assim; de repente ela apareceu 3 ou 4 testes depois!), e por ser algo que a funcionalidade inicial precisa, acabou virando um método privado dentro dessa classe. Esse método privado começa a crescer tanto que você quer testá-lo.

O que fazer? Extraia esse comportamento para uma nova classe. Essa nova classe será responsável somente por isso. Em seguida, faça a primeira classe depender dessa nova classe. Você conseguirá dar um nome bem significativo para essa nova classe, pois ela muito provavelmente representa um conceito de domínio, que até então estava escondido.

Extrair comportamentos para novas classes é algo muito comum ao se fazer TDD. Conforme o programador vai evoluindo a funcionalidade, novas responsabilidades aparecem e é muito tentador colocar todas elas no mesmo lugar. Que sorte a nossa termos o teste pra nos avisar! :)

Referências:

Martin, Robert. Principles of OOD. http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

Feathers, Michael. The Deep Synergy between Testability and Good Design. http://michaelfeathers.typepad.com/michael_feathers_blog/2007/09/the-deep-synerg.html

Caroli, Paulo. Testing Private Methods, TDD and Test-Driven Refactoring. http://agiletips.blogspot.com/2008/11/testing-private-methods-tdd-and-test.html, 2008.

Share

Segundo o livro Use a Cabeça: Desenvolvimento de Softwares, a definição de PRE é: Cada objeto de seu sistema deve ter uma responsabilidade exclusiva e todos os serviços do objeto devem estar orientados à execução dessa responsabilidade. Em outras palavras, uma classe deve ser responsável por uma determinada função, e só ela pode exercê-la.

Uma classe Carro, por exemplo, deve ser unica e exclusivamente responsável por realizar funções de um carro (como medir óleo, acender farol, etc). A classe Carro não deve ser responsável por saber se lavar (essa é uma responsabilidade que poderia ser entregue a uma classe LavaRapido, por exemplo).

Conversando hoje com o Murilo Amêndola, discutimos sobre como saber quais as responsabilidades de uma classe. Concordamos que não é uma tarefa trivial e que depende de muita experiência para que todas suas classes tenham um alto nível de coesão. Lendo hoje um trecho do livro citado acima, encontrei um algoritmo muito interessante para saber se determinada responsabilidade deve ou não pertencer a determinada classe. Vou reproduzí-lo aqui:

  1. Escreva, em uma folha de papel, várias linhascomo essa: O [espaço] [espaço] sozinho. Escreva 1 linha dessa para cada método da classe que você está testando quanto ao PRE.
  2. No primeiro espaço em branco de cada linha, preencha o nome da classe. No segundo espaço em branco, anote um dos métodos da classe. Faça isso para todos os métodos.
  3. Leia cada linha em voz alta. Você pode até adicionar uma letra ou palavra para que a leitura fique adequada. Se a frase que você disse fez algum sentido, então esse método realmente pertence a essa classe. Se não fizer nenhum sentido, então provavalmente esse método não pertence a essa classe.

Voltando ao exemplo da classe Carro:

  • O carro se liga sozinho. (CERTO)
  • O carro se desliga sozinho. (CERTO)
  • O carro trocaPneus sozinho. (ERRADO)
  • O carro dirige sozinho. (ERRADO)
  • O carro se lava sozinho. (ERRADO)
  • O carro medeOleo sozinho. (CERTO)

Repare que faz todo sentido o carro medir óleo sozinho, enquanto não faz sentido nenhum o carro se dirigir sozinho (esse método deveria estar em uma classe Motorista), ou se lavar sozinho (deveria ser responsabilidade da classe LavaRapido)!

O método liga e desliga não fazem taaanto sentido (afinal, um carro não se liga sozinho), mas nesse caso, não vejo outra alternativa (é o carro que sabe como se ligar!). Isso mostra que a regra acima é apenas uma diretriz, e por isso você deve usar de bom senso e de sua experiência.

O interessante é que você pode adaptar essa regra até para métodos que recebem parâmetros. Se você tiver um método troca(peça), você escreve a seguinte sentença: O carro troca [uma]  peça sozinho. No caso, também não faz muito sentido, você poderia ter uma classe Mecânico, com o método troca(peça, carro).

Enfim, é uma análise interesse, não acham?

(Exemplo retirado do livro Use a Cabeça: Desenvolvimento de Softwares, capítulo 5.)

Share
© 2011 Mauricio Aniche Suffusion theme by Sayontan Sinha