[quote=gomesrod][quote=heliofrota]
Patrick Volkerding:
[/quote]
Isso traduz bem o que penso: testes unitários onde eles são necessários.
Geralmente uso em rotinas que executam lógicas complexas ou razoavelmente complexas, mas sem essa obrigação de 100% de cobertura. Por exemplo, um determinado parâmetro não informado lança uma exceção. Não crio um teste para isso pois está bastante óbvio o comportamento do código.
Outros pontos que o pessoal às vezes faz malabarismos com mock apenas para conseguir cobertura de 100%: Actions/Controllers, Serviços que só delegam ao DAO.[/quote]
Gostaria de comentar algumas coisas aqui. Não realmente responder ao autor do trecho acima, mas tocar os pontos texto.
Primeiro ha que distinguir “teste” de "test-drive-developement’ (aka TDD) e “test-first”. Também destinguir “teste” de “experiencia”.
É muito comum ouvir a frase “teste de mesa”. Isto não existe. O que se quer dizer é “experiencia de mesa”. O programador após criar o código experimenta se ele funciona. E fica experimentando até que o código faz o que ele espera.
É certo que os programadores só fazem experiencia quando têm dúvidas se o código funciona. Ninguém experimenta 2+ 2 , mas provavelmente vão experimental BigDecimal.divide() porque tem 2 argumentos em vez de um, que seria o de esperar. E mesmo tem gente que usar o junit para criar experiencias mais complexas e avançadas. Mas são experiencias.
Teste é algo mais técnico. Primeiro ha que saber onde podem estar as falhas, criar cenários (passo-a-passo) para exercitar essas falhas. Os chamados “corner cases” são importantes. Incluir regras de qualidade (por exemplo, o método nunca deve retornar os parametros que recebeu, ou o método não deve aceitar nulo, o objeto é realmente imutável). Depois código é escrito para realizar estas verificações. A diferença é que um teste é criado sem saber nada sobre o código a ser testado e sim sobre a unidade sob test ( classe, sistema, etc). Apenas quem escreve o código do teste tem que se preocupar com isto.
Estes testes são raros a menos que haja investimento da instituição e das equipes.
Test-Fisrt é simplesmente a prática de criar o teste antes de programar a unidade (classe, sistema, etc…) a ser testada. Desta forma, apenas quando criarmos o código de teste iremos nos preocupar com a real interface da unidade, mas não para fazer a lista de coisas a testar.
TDD é abusar do conceito de Test-First para ajudar no desenvolvimento. Ou seja, o código do teste é utilizado para guiar como será a interface da unidade sob teste, quantos e quais outras unidades serão necessárias, como elas interagem etc… ou seja, é simplesmente modelar o código melhor usando o cheklist de testes para prover um melhor desing. Por exemplo, Testar um singleton é um parto, então, usando TDD irá criar um outro design mais simples de testar e que obtém os mesmos resultados.
Isto nada mais é que a velha prática de criar mais do que um cliente para o seu código. O código de teste que chama o seu business é tao importante quanto o código do action que chama o business. São ambos dois clientes válidos para o business.
Não confundir TDD com Test-First. O primeiro é um receiturário de processo de desenvolvimento (não de teste), o segundo é uma Diretiva de Desenvolvimento ( usada, por exemplo, no XP)
Só um ponto de ordem, todos os testes são unitários , o que muda é a unidade que pode ser um classe, uma instancia de uma classe, um conjunto de classes, um conjunto de instancias, um sistema completo, um conjunto de sistema. Nome variados são usados para agrupar as coias como teste de integração e coisas assim, mas quando se fala em “Unit Test” não se está falando em teste onde a unidade é o mais baixo possivel, e sim na metodologia geral de testes. “Unit test” significa teste no sentido que expliquei antes, para não confundir com “experiencia”.
Dado isto, a resposta do Pratick não é “Não quero saber de testes unitários” é “Eu escrevo testes, e ocasionalmente usando o principio do Test-First, mas não desenvolvo meu código usando os testes” ou seja, ele desenvolve o código como qualquer um faria, usando a experiencia, imaginação e um plano mental do que ha fazer e como, e depois escreve os testes do que realizou. E às vezes, ele escreve primeiro o teste - provavelmente para deixar bem claro para ele mesmo o que ha a ser feito e quais os riscos.
Em nenhum ponto ele escreveu “eu não escrevo testes” ou “só escrevo quando me apetece” ou “só escrevo quando acho que é necessário”.
É fácil mal-intepretar as respostas, mas o ponto é simples : Testes Unitários (os que não são experiencias) sim são importantes e vitais.
Ninguém disse que é fácil. Ninguém disse que é rápido. Mas todos concordam que é importante e vital.
Ok, não preciso criar o teste antes. É muito útil se fizer isso, mas isso não é tão importante. O importante é que o teste exista.
Por outro lado, quando se programa é muito simples criar estruturas que não são fáceis de testar. É para evitar isso que existe o TDD e o Test-First. Mas se você sá sabe criar bom código, que é simples de testar, vc simplesmente vai lá e escreve o código.
Se o código é bom, não importa realmente a ordem. Agora, se o código é ruim, ou o programador não sabe o que está fazendo, então sim, estes princípios são importantes até que o gramador ganhe uma maestria do design.
Por outro lado, os testes não são criados para ver se o código funciona. Isto é um pensamento errado. Não estamos querendo saber se sódio com cloro dá sal. Não é uma investigação. Não é um experimento. O que queremos com isto é ter um mecanismo automatizado que nos diga que o sistema ainda está funcionando. É esta segurança que procuramos e não se o sistema funciona. Porque é esta segurança que nos permitirá realizar modificações sem medo pois existe outra diretiva que diz “Não tenha medo de refactorar”. Vc pode ter medo que o seu codigo seja impossível, caro, ou lento de refactorar, ou que refactorando ele deixe de funcionar. Esses são medos válidos e são eliminados usando, por exemplo, testes automáticos. Ter medo que deixe de funcionar é normal, ficar paralizado por isso não é.
Cobertura de 100% é impossível. O normal é 30-50% e 70% é absurdamente bom. Mas claro, testar todos os get/set não conta nesta cobertura. Além disso testes são incrementais. Começa por testar o que você espera que possa dar errado. Depois, vc vai receber tikets com erros que mostra que alguns cenários vc não previu e vc adiciona mais testes e assim vai… ninguém testa tudo da primeira vez. Seria insano.
Criar testes é dificil, caro , demorado e muitas vezes mais dificil que criar o próprio sistema. Eu vivo isto todos os dias, não apenas no trabalho, mas no meu projeto pessoal que tem mais de 60 mil linhas de código e 1900 classes. Para tudo isto tenho 127 testes com 16% de cobertura - muito pouco. Mas não vale me enganar achando que o mais importantes é o código e que não preciso dos testes. É claro que preciso. Muitos refactorings são feitos na fé e isso não é bom. Não vale me enganar dizendo que se o Spring ou o JDK não têm testes eu também não preciso. Não vale tentar arranjar desculpas para não fazer os testes.
Então vamos parar com essa ideia que existe a mínima chance de não ter que escrever testes. Não ha!. Pode ser preguiçoso, pode ter falta de tempo, recursos e até de conhecimento de como fazer os testes, mas dizer que eles não são necessários é simplesmente burrice. É como dizer que o cinto de segurança não é necessário.
Eu já convivi com vários projetos que não têm testes automáticos. Ok, funciona. Até que descobrimos que não funciona. E quando descobrimos isso e precisamos refatorar - valha-nos Deus. E se queremos melhorar o sistema em algum ponto , logo alguém grita “Não! pode quebrar”. É claro que pode quebrar. A questão é se vamos saber. Se ha um mecanismo automático que testa o pontos vitais mais preocupantes e se esses continuam funcionando podemos dizer que o refactoring foi um sucesso. Mas e quando não temos os testes ? E pior, quando temos um código que é impossível testar ? Ai é pior ainda, porque para criar os testes teríamos que refatorar o sistema primeiro (!). O risco envolvido nisto é insano. E como disse Einstein, insanidade é repetir a mesma coisa e esperar resultados diferentes. Portanto, deixar o sistema sem testes e esperar que ele não vai dar problema é tão insano quanto criar um sistema impossível de testar.
Quanto a só usar sistemas com testes, o argumento é uma falácia logo no inicio. Os testes não são para proteger o cliente e o usuário, são proteger o investimento e a equipe de desenvolvimento. O cliente simplesmente mudar de sistema se ele dá problema ou processa a empresa por danos. Ou seja, é risco. Os testes servem para mitigar risco no desenvolvimento, não para salvar o usuário.