Eu sou pago por código que funciona, não por testes, então minha filosofia é testar o mínimo possível para alcançar um determinado nível de confiança (suspeito que esse nível de confiança seja alto em comparação com os padrões da indústria, mas isso pode ser apenas arrogância) . Se eu normalmente não cometer um tipo de erro (como definir as variáveis erradas em um construtor), não testo. Eu tendo a entender os erros de teste, então sou extremamente cuidadoso quando tenho lógica com condicionais complicadas. Ao codificar em equipe, modifico minha estratégia para testar cuidadosamente o código que, coletivamente, tendemos a errar.
Pessoas diferentes terão estratégias de teste diferentes com base nessa filosofia, mas isso parece razoável para mim, dado o estado imaturo de compreensão de como os testes podem se encaixar melhor no loop interno da codificação. Daqui a dez ou vinte anos, provavelmente teremos uma teoria mais universal sobre quais testes escrever, quais testes não escrever e como saber a diferença. Nesse ínterim, a experimentação parece adequada.
Escreva testes de unidade para coisas que você espera quebrar e para casos extremos. Depois disso, os casos de teste devem ser adicionados à medida que os relatórios de bug chegam - antes de escrever a correção para o bug. O desenvolvedor pode ter certeza de que:
De acordo com o comentário anexado - acho que essa abordagem para escrever testes de unidade pode causar problemas, se muitos bugs forem, com o tempo, descobertos em uma determinada classe. Provavelmente, é aqui que a discrição é útil - adicionar testes de unidade apenas para bugs que provavelmente ocorrerão novamente ou onde sua recorrência causaria problemas sérios. Descobri que uma medida de teste de integração em testes de unidade pode ser útil nesses cenários - codepaths superiores de teste de código podem cobrir os codepaths inferiores.
fonte
Uma das coisas mais incompreendidas sobre o TDD é a primeira palavra nele. Teste. É por isso que o BDD apareceu. Porque as pessoas realmente não entendiam que o primeiro D era o importante, ou seja, Driven. Todos nós tendemos a pensar um pouco demais sobre o Teste, e um pouco ou pouco sobre a condução do design. E eu acho que esta é uma resposta vaga para sua pergunta, mas você provavelmente deve considerar como conduzir seu código, em vez do que você realmente está testando; isso é algo em que uma ferramenta de cobertura pode ajudá-lo. O design é uma questão muito maior e mais problemática.
fonte
Para aqueles que propõem testar "tudo": percebam que "testar totalmente" um método como
int square(int x)
requer cerca de 4 bilhões de casos de teste em linguagens comuns e ambientes típicos.Na verdade, é ainda pior do que isso: um método
void setX(int newX)
também é obrigado não alterar os valores de quaisquer outros membros alémx
- você está testando queobj.y
,obj.z
etc. todos permanecem inalteradas depois de chamarobj.setX(42);
?É apenas prático testar um subconjunto de "tudo". Depois de aceitar isso, torna-se mais palatável considerar não testar um comportamento incrivelmente básico. Cada programador tem uma distribuição de probabilidade da localização do bug; a abordagem inteligente é concentrar sua energia em regiões de teste onde você estima que a probabilidade de bug seja alta.
fonte
A resposta clássica é "teste qualquer coisa que possa quebrar". Eu interpreto isso como significando que testar setters e getters que não fazem nada exceto set ou get é provavelmente muito teste, não há necessidade de perder tempo. A menos que seu IDE escreva para você, você também pode.
Se o seu construtor não definir as propriedades pode levar a erros mais tarde, então testar se elas estão definidas não é um exagero.
fonte
Eu escrevo testes para cobrir as suposições das aulas que irei escrever. Os testes reforçam os requisitos. Essencialmente, se x nunca pode ser 3, por exemplo, vou garantir que haja um teste que cubra esse requisito.
Invariavelmente, se eu não escrever um teste para cobrir uma condição, ele aparecerá mais tarde durante o teste "humano". Certamente escreverei um então, mas prefiro pegá-los logo. Acho que o ponto é que o teste é tedioso (talvez), mas necessário. Eu escrevo testes suficientes para serem concluídos, mas não mais do que isso.
fonte
Parte do problema de pular testes simples agora está no futuro, a refatoração poderia tornar essa propriedade simples muito complicada com muita lógica. Acho que a melhor ideia é que você pode usar testes para verificar os requisitos para o módulo. Se, ao passar em X, você receber Y de volta, é isso que você deseja testar. Então, quando você alterar o código posteriormente, poderá verificar se X fornece Y e pode adicionar um teste para A fornece B, quando esse requisito for adicionado posteriormente.
Descobri que o tempo que gasto durante o desenvolvimento inicial escrevendo testes compensa na primeira ou na segunda correção de bug. A capacidade de pegar um código que você não olha em 3 meses e ter certeza razoável de que sua correção cobre todos os casos e "provavelmente" não quebra nada é extremamente valiosa. Você também descobrirá que os testes de unidade ajudarão a fazer a triagem de bugs muito além do rastreamento da pilha, etc. Ver como partes individuais do aplicativo funcionam e falham fornece uma grande percepção de por que funcionam ou falham como um todo.
fonte
Na maioria dos casos, eu diria, se houver lógica, teste-a. Isso inclui construtores e propriedades, especialmente quando mais de uma coisa é definida na propriedade.
Com relação a muitos testes, é discutível. Alguns diriam que tudo deve ser testado quanto à robustez, outros dizem que, para testes eficientes, apenas coisas que podem falhar (ou seja, a lógica) devem ser testadas.
Eu me inclinaria mais para o segundo campo, apenas por experiência pessoal, mas se alguém decidisse testar tudo, eu não diria que foi demais ... um pouco exagerado talvez para mim, mas não muito para eles.
Portanto, não - eu diria que não há testes "demais" no sentido geral, apenas para indivíduos.
fonte
Desenvolvimento Orientado a Testes significa que você interrompe a codificação quando todos os seus testes forem aprovados.
Se você não tem um teste para uma propriedade, por que deveria implementá-lo? Se você não testar / definir o comportamento esperado no caso de uma atribuição "ilegal", o que a propriedade deve fazer?
Portanto, estou totalmente a favor de testar todos os comportamentos que uma classe deve apresentar. Incluindo propriedades "primitivas".
Para tornar esse teste mais fácil, criei um NUnit simples
TestFixture
que fornece pontos de extensão para definir / obter o valor e leva listas de valores válidos e inválidos e tem um único teste para verificar se a propriedade funciona bem. O teste de uma única propriedade pode ser assim:Usando lambdas e atributos, isso pode até ser escrito de forma mais compacta. Percebi que o MBUnit tem até suporte nativo para coisas assim. O ponto, porém, é que o código acima captura a intenção da propriedade.
PS: Provavelmente o PropertyTest também deve ter uma maneira de verificar se outras propriedades do objeto não foram alteradas. Hmm .. de volta à prancheta de desenho.
fonte
Eu faço teste de unidade para alcançar a cobertura máxima viável. Se eu não conseguir alcançar algum código, eu refatoro até que a cobertura esteja o mais completa possível
Depois de terminar o teste de escrita ofuscante, geralmente escrevo um caso de teste reproduzindo cada bug
Estou acostumado a separar entre teste de código e teste de integração. Durante o teste de integração (que também são testes de unidade, mas em grupos de componentes, portanto, não exatamente para o que os testes de unidade servem), testarei os requisitos a serem implementados corretamente.
fonte
Portanto, quanto mais eu conduzo minha programação escrevendo testes, menos me preocupo com o nível de granualidade dos testes. Olhando para trás, parece que estou fazendo a coisa mais simples possível para atingir meu objetivo de validar o comportamento . Isso significa que estou gerando uma camada de confiança de que meu código está fazendo o que eu peço; no entanto, isso não é considerado uma garantia absoluta de que meu código está livre de bugs. Eu sinto que o equilíbrio correto é testar o comportamento padrão e talvez um caso extremo ou dois e então passar para a próxima parte do meu projeto.
Aceito que isso não cobrirá todos os bugs e uso outros métodos de teste tradicionais para capturá-los.
fonte
Geralmente, começo pequeno, com entradas e saídas que sei que devem funcionar. Então, conforme eu corrijo os bugs, adiciono mais testes para garantir que as coisas que consertei sejam testadas. É orgânico e funciona bem para mim.
Você pode testar muito? Provavelmente, mas provavelmente é melhor errar no lado da cautela em geral, embora isso dependa de quão crítico é o seu aplicativo.
fonte
Acho que você deve testar tudo em seu "núcleo" de sua lógica de negócios. Getter e Setter também porque eles podem aceitar valores negativos ou nulos que você pode não querer aceitar. Se você tiver tempo (sempre dependa do seu chefe) é bom testar outras lógicas de negócios e todos os controladores que chamam esses objetos (você vai do teste de unidade ao teste de integração aos poucos).
fonte
Eu não faço testes de unidade com métodos setter / getter simples que não têm efeitos colaterais. Mas eu faço testes de unidade em todos os outros métodos públicos. Tento criar testes para todas as condições de contorno em meus algoritmos e verifico a cobertura de meus testes de unidade.
É muito trabalho, mas acho que vale a pena. Eu preferiria escrever código (mesmo testar código) do que percorrer o código em um depurador. Acho que o ciclo de código-construção-implantação-depuração consome muito tempo e quanto mais exaustivos os testes de unidade que integrei em minha construção, menos tempo gasto passando por esse ciclo de código-construção-implantação-depuração.
Você não disse por que a arquitetura também está codificando. Mas para Java eu uso Maven 2 , JUnit , DbUnit , Cobertura e EasyMock .
fonte
Quanto mais leio sobre isso, mais acho que alguns testes de unidade são como alguns padrões: Um cheiro de línguas insuficientes.
Quando você precisa testar se seu getter trivial realmente retorna o valor correto, é porque você pode misturar o nome do getter e o nome da variável de membro. Digite 'attr_reader: nome' de ruby, e isso não pode mais acontecer. Simplesmente não é possível em java.
Se seu getter se tornar não trivial, você ainda pode adicionar um teste para ele.
fonte
Teste o código-fonte que o preocupa.
Não é útil testar partes do código nas quais você tem muita confiança, contanto que não cometa erros nelas.
Teste as correções de bugs, para que seja a primeira e a última vez que você conserta um bug.
Teste para obter confiança em partes obscuras do código, para que você crie conhecimento.
Teste antes da refatoração pesada e média, para não quebrar os recursos existentes.
fonte
Essa resposta é mais para descobrir quantos testes de unidade usar para um determinado método que você sabe que deseja testar de unidade devido à sua criticidade / importância. Usando a técnica de Teste de Caminho de Base da McCabe, você poderia fazer o seguinte para ter uma melhor confiança de cobertura de código quantitativa do que a simples "cobertura de instrução" ou "cobertura de ramificação":
fonte