Contexto:
Atualmente, estou trabalhando em um pequeno projeto em Python. Geralmente estruturo minhas classes com alguns métodos públicos documentados, mas principalmente com os conceitos de alto nível (o que um usuário da classe deve conhecer e usar) e vários métodos ocultos (começando com sublinhado) que são responsáveis pelo processamento complexo ou de baixo nível.
Eu sei que os testes são essenciais para garantir a confiança no código e garantir que qualquer modificação posterior não interrompa o comportamento anterior.
Problema:
Para criar os métodos públicos de nível superior em uma base confiável, geralmente testo os métodos privados. Acho mais fácil descobrir se uma modificação de código introduziu regressões e onde. Isso significa que esses testes internos podem violar revisões menores e precisarão ser corrigidos / substituídos
Mas também sei que o método privado de teste de unidade é pelo menos um conceito disputado ou mais frequentemente considerado como uma má prática. A razão é: apenas o comportamento público deve ser testado ( ref. )
Questão:
Eu me preocupo em seguir as melhores práticas e gostaria de entender:
- por que o uso de testes de unidade em métodos privados / ocultos é ruim (qual é o risco)?
- Quais são as melhores práticas quando os métodos públicos podem usar processamento de baixo nível e / ou complexo?
Precisões:
- não é um como questionar. Python não tem um conceito verdadeiro de privacidade e métodos ocultos simplesmente não estão listados, mas podem ser usados quando você souber o nome deles
- Nunca aprendi regras e padrões de programação: minhas últimas aulas são dos anos 80 ... Aprendi principalmente idiomas por tentativa e falha e referências na Internet (o Stack Exchange é o meu favorito há anos)
fonte
Respostas:
Um par de razões:
Normalmente, quando você é tentado a testar o método privado de uma classe, é um cheiro de design (classe de iceberg, componentes públicos reutilizáveis insuficientes etc.). Quase sempre há algum problema "maior" em jogo.
Você pode testá-los através da interface pública (que é como você deseja testá-los, porque é assim que o cliente os chama / usa). Você pode obter uma falsa sensação de segurança vendo a luz verde em todos os testes aprovados nos seus métodos particulares. É muito melhor / mais seguro testar casos extremos em suas funções privadas por meio de sua interface pública.
Você corre o risco de duplicação severa de testes (testes que parecem muito similares) testando métodos privados. Isso tem grandes conseqüências quando os requisitos mudam, pois mais testes do que o necessário serão interrompidos. Ele também pode colocá-lo em uma posição em que é difícil refatorar por causa do seu conjunto de testes ... o que é a ironia final, porque o conjunto de testes existe para ajudá-lo a redesenhar e refatorar com segurança!
Uma dica, se você ainda está tentado a testar as partes privadas (não a use se isso a incomoda e ao YMMV, mas funcionou bem para mim no passado): Às vezes, escrevendo testes de unidade para funções privadas apenas para garantir eles estão trabalhando exatamente como você pensa que podem ser valiosos (especialmente se você é novo em um idioma). No entanto, depois de ter certeza de que eles funcionam, exclua os testes e sempre verifique se os testes voltados ao público são sólidos e serão capturados se alguém fizer uma alteração flagrante na referida função privada.
Quando testar métodos particulares: Como essa resposta se tornou (um pouco) popular, sinto-me obrigado a mencionar que uma "melhor prática" é sempre apenas isso: uma "melhor prática". Isso não significa que você deve fazer isso dogmaticamente ou cegamente. Se você acha que deveria testar seus métodos particulares e ter um motivo legítimo (como se estivesse escrevendo testes de caracterização para um aplicativo herdado), teste seus métodos privados . Circunstâncias específicas sempre superam qualquer regra geral ou melhor prática. Esteja ciente de algumas das coisas que podem dar errado (veja acima).
Eu tenho uma resposta que detalha isso em detalhes no SO, que não repetirei aqui: /programming/105007/should-i-test-private-methods-or-only-public-ones/ 47401015 # 47401015
fonte
bin_search(arr, item)
(público) ebin_search(arr, item, low, hi)
(privado, há muitas maneiras de fazer pesquisa em bin), tudo o que você precisa para testar é o público (bin_search(arr, item)
)Dado que um dos principais objetivos dos testes de unidade é que você pode refatorar as partes internas do seu programa e poder verificar se não quebrou sua funcionalidade, é contraproducente se seus testes de unidade operarem com um nível de granularidade tão bom que qualquer alteração no código do programa exige que você reescreva seus testes.
fonte
Escrever testes de unidade para métodos particulares vincula seus testes de unidade aos detalhes da implementação.
Os testes de unidade devem testar o comportamento de uma classe na superfície externa da classe (é API pública). Os testes de unidade não precisam saber nada sobre as entranhas de uma classe. Escrever testes de unidade nos detalhes de implementação de uma classe amarra suas mãos quando chega a hora de refatorar. A refatoração quase certamente vai quebrar esses testes, porque eles não fazem parte da sua API estável.
Dito isto, por que você pode querer escrever testes de unidade para seus métodos particulares?
Há uma tensão natural entre testes de unidade e desenvolvimento incremental. Os desenvolvedores de software que usam um REPL (loop de leitura e avaliação) podem atestar o quão produtivo pode ser para escrever e testar rapidamente pequenos pedaços de funcionalidade à medida que você "cresce" uma classe ou função. A única boa maneira de fazer isso em ambientes controlados por teste de unidade é escrever testes de unidade para métodos privados, mas há muito atrito em fazer isso. Os testes de unidade levam tempo para serem escritos, você precisa de um método real para testar e sua estrutura de teste precisa oferecer suporte à capacidade de manter o método privado, para que não polua sua API externa.
Alguns ecossistemas como C # e .NET têm maneiras de criar ambientes semelhantes a REPL (ferramentas como o Linqpad fazem isso), mas seu utilitário é limitado porque você não tem acesso ao seu projeto. A janela imediata no Visual Studio é inconveniente; ele ainda não possui o Intellisense completo, é necessário usar nomes totalmente qualificados e acionar uma compilação toda vez que você o usar.
fonte
Pela minha experiência, descobri que os testes unitários das classes internas, métodos geralmente significa que eu tenho que retirar as funções testadas, as classes. Para criar outro nível de abstração.
Isso leva a uma melhor aderência ao Princípio da Responsabilidade Única.
fonte
Penso que esta é uma boa pergunta, pois expõe um problema comum na cobertura de testes. Mas uma boa resposta deve lhe dizer que a pergunta não está exatamente correta porque, em teoria, você não deve poder testar métodos particulares . É por isso que eles são privados .
Talvez uma pergunta melhor seja "O que devo fazer quando quiser testar métodos particulares?" , e a resposta é meio óbvia: você deve expô-los de uma maneira que torne possível o teste. Agora, isso não significa necessariamente que você deve apenas tornar público o método e é isso. Muito provavelmente você desejará fazer uma abstração mais alta; vá para uma biblioteca ou API diferente para poder fazer seus testes nessa biblioteca, sem expor essa funcionalidade na sua API principal.
Lembre-se de que há uma razão pela qual seus métodos têm diferentes níveis de acessibilidade e você deve sempre pensar em como suas aulas serão usadas no final.
fonte