Às vezes, funções privadas de um módulo ou classe são simplesmente unidades internas de funcionalidade ainda a serem extraídas, que podem merecer seus próprios testes. Então, por que não testá-los? Nós vai escrever testes para eles mais tarde, se / quando eles são extraídos. Então, por que não escrever os testes agora, quando eles ainda fazem parte do mesmo arquivo?
Para demonstrar:
Primeiro eu escrevi module_a
. Agora eu quero escrever testes para isso. Eu gostaria de testar a função 'privada' _private_func
. Eu não entendo por que não escreveria um teste para ele, se mais tarde eu poderia refatorá-lo para seu próprio módulo interno e, em seguida, escrever testes para ele.
Suponha que eu tenha um módulo com as seguintes funções (também pode ser uma classe):
def public_func(a):
b = _do_stuff(a)
return _do_more_stuff(b)
_do_stuff
e _do_more_stuff
são funções 'privadas' do módulo.
Entendo a ideia de que devemos testar apenas a interface pública, não os detalhes da implementação. No entanto, aqui está a coisa:
_do_stuff
e _do_more_stuff
contém a maioria das funcionalidades do módulo. Cada um deles poderia ser uma função pública de um módulo 'interno' diferente. Mas eles ainda não foram desenvolvidos e são grandes o suficiente para serem extraídos para separar arquivos.
Portanto, testar essas funções parece certo porque são unidades importantes de funcionalidade. Se eles estivessem em módulos diferentes como funções públicas, nós os teríamos testado. Então, por que não testá-los quando ainda não foram (ou nunca) extraídos para um arquivo diferente?
Respostas:
A necessidade de testar não é a mesma que ser pública.
Código não trivial precisa ser testado independentemente da exposição. O comportamento não público não precisa existir e muito menos ser testado.
Essas visões conflitantes podem levar você a querer tornar pública todas as funções ou se recusar a incluir o código em uma função, a menos que seja pública.
Esta não é a resposta. Esteja disposto a criar funções auxiliares privadas. Teste-os através da interface pública que o utiliza o máximo possível.
Se o teste através da interface pública não exercer suficientemente a função privada, a função privada está tentando permitir muito.
A validação pode ajudar a restringir o que a função privada permite. Se você não conseguir passar um nulo pela interface pública, ainda poderá lançar uma exceção, se houver, de qualquer maneira.
Por que você deveria? Por que testar o que você nunca verá? Porque as coisas mudam. Pode ser privado agora, mas ser público mais tarde. O código de chamada pode mudar. O código que rejeita explicitamente nulo torna claro o uso adequado e o estado esperado.
Claro que nulo poderia estar bem. É apenas um exemplo aqui. Mas se você espera algo, é útil deixar essa expectativa clara.
Esse pode não ser o tipo de teste que você tinha em mente, mas espero que esteja disposto a criar funções auxiliares privadas, quando apropriado.
O desejo de testar é bom, mas não deve ser a força motriz no design da sua API pública. Projete a API pública para ser fácil de usar. Provavelmente não será se todas as funções forem públicas. A API deve ser algo que as pessoas possam entender como usar sem mergulhar no código. Não deixe essas pessoas se perguntando para que serve essa função auxiliar estranha.
Ocultar funções auxiliares públicas em um módulo interno é uma tentativa de respeitar a necessidade de uma API limpa enquanto expõe auxiliares para teste. Não direi que isso está errado. Você pode estar dando o primeiro passo em direção a uma camada arquitetural diferente. Mas, por favor, domine a arte de testar funções auxiliares privadas através das funções públicas que as utilizam primeiro. Dessa forma, você não usará mais essa solução alternativa.
fonte
Resposta curta: Não
Resposta mais longa: Sim, mas através da 'API' pública da sua classe
A idéia dos membros privados de uma classe é que eles representem funcionalidades que devem ser invisíveis fora da 'unidade' do código, por maior que você queira definir essa unidade. No código orientado a objetos, essa unidade geralmente acaba sendo uma classe.
Você deve ter sua classe projetada de forma que seja possível invocar toda a funcionalidade privada por meio de várias combinações de estado de entrada. Se você achar que não existe uma maneira relativamente direta de fazer isso, provavelmente é uma sugestão de que seu design precisa de mais atenção.
Após o esclarecimento da questão, isso é apenas uma questão de semântica. Se o código em questão puder operar como uma unidade autônoma separada e estiver sendo testado como se fosse um código público, não vejo nenhum benefício em não movê-lo para um módulo autônomo. No momento, serve apenas para confundir futuros desenvolvedores (inclusive você, em seis meses), por que o código aparentemente público está oculto dentro de outro módulo.
fonte
O ponto principal das funções privadas é que elas são detalhes ocultos da implementação que podem ser alterados à vontade, sem alterar a API pública. Para o seu código de exemplo:
Se você tiver uma série de testes que apenas usam
public_func
, se você a reescrever para:então, desde que o resultado de retorno para um valor específico
a
permaneça o mesmo, todos os seus testes serão bons. Se o resultado do retorno mudar, um teste falhará, destacando o fato de que algo ocorreu.Tudo isso é bom: API pública estática; funcionamento interno bem encapsulado; e testes robustos.
No entanto, se você tivesse escrito testes para
_do_stuff
ou_do_more_stuff
feito a alteração acima, agora terá vários testes quebrados, não porque a funcionalidade mudou, mas porque a implementação dessa funcionalidade mudou. Esses testes precisariam ser reescritos para funcionar com as novas funções, mas, com eles funcionando, tudo que você saberia é que esses testes funcionavam com as novas funções. Você teria perdido os testes originais e, portanto, não saberia se o comportamentopublic_func
havia mudado; portanto, os testes seriam basicamente inúteis.Isso é ruim: uma API em mudança; trabalhos internos expostos firmemente acoplados a testes; e testes frágeis que mudam assim que são feitas mudanças na implementação.
Portanto, não, não teste funções privadas. Sempre.
fonte