Você quer testar métodos privados? Certeza?

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.

13 thoughts on “Você quer testar métodos privados? Certeza?

  1. Pingback: Tweets that mention Você quer testar métodos privados? Certeza? | Mauricio Aniche -- Topsy.com

  2. Prodis a.k.a. Fernando Hamasaki de Amorim

    Concordo plenamente.
    Às vezes a pessoa até sabe que o melhor caminho é extrair a funcionalidade do método privado e depois injetar a classe criada, mas por comodismo acaba não fazendo isso e testando o método privado. Ainda mais quando a ferramenta utilizada para testes, como o MSTest por exemplo, tem recursos que facilita o acesso aos métodos privados.

    Mas também já vi situações em que o “programador” altera a visibilidade do método para pública, mantendo na mesma classe e aí faz o teste isolado desse método. Aí a coisa começa a descambar para um lado sombrio.

    Reply
  3. Diego Caxito

    Concordo em partes com o colocado no post. Aliado a este ponto, gostaria de acrescentar que não há sempre a necessidade de extrair tal método para outra classe.

    Você pode cair também na situação em que um método privado foi acrescentado para manutenção da legibilidade do código que compõe o método público. Este último que deve ter seus comportamentos testados. Esta última abordagem mantém os testes em torno do domínio em questão, pouco importando por quantos métodos ele é composto.

    A beleza fica no teste do domínio público como um todo, não importando com as formas que o compõe.

    Bom ponto de vista do post, parabéns, abraço.

    Reply
  4. admin Post author

    @Paulo Caroli,

    Perfeito! Seu post explicou na prática o que eu disse apenas na teoria! 🙂

    Se não se importar, estou adicionando-o na lista de referências!

    Reply
  5. Vinicius Quaiato

    E aquele papo:
    Se estou escrevendo um aprser de qualquer coisa, e só quero que minha API exponha:
    Parser.Parse(algumTexto);

    Em um primeiro momento, o Parser é quem faz tudo, por exemplo:
    private IList ParseHifenizedTokens(string textToParse);
    e mais outros
    private IList ParseEmptySpacedTokens(string textToParse);

    Eu concordo com não testar métodos privados, mas no exemplo acima, você criaria mesmo uma classe para este parse, mesmo NÃO querendo expor isso na sua API?
    Usaria InternalsVisibleTo?

    Abraços,
    Vinicius Quaiato.

    Reply
  6. mauricioaniche Post author

    Você poderia por essas responsabilidades de tokenizar em uma classe chamada Tokenizer, por exemplo. Sua classe Parser faria uso dela! Algo como:

    public class Parser {
      public Parser(ITokenizer tokenizer) { ... }
      public AlgumaCoisa Parse(string contentToBeParsed) { 
        // faz uso do tokenizer 
      }
    }
    

    Faz sentido? 🙂

    Reply
  7. Pingback: O melhor da semana 31/10 a 06/11 « QualidadeBR

  8. Pingback: Mudanças simples x Soluções simples | blog.caelum.com.br

  9. Wilson

    Dessa forma, métodos privados não deveriam existir em nossas aplicações?
    Muito bom o texto, só ficou essa dúvida mesmo…
    Valeu.

    Reply
  10. mauricioaniche Post author

    Oi Wilson,

    Sim, métodos privados devem existir! O problema que tentei atacar é justamente quando eles crescem demais! Aí talvez esse método privado não deva ser mais um simples método e sim uma classe!

    Faz sentido?

    Abraços,
    Mauricio

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *