O programador profissional precisa de testes unitários?

Peraí que você esta me confundindo, Rodrigo, O teste unitário é para testar a menor unidade do meu código, e no caso de Java é o a classe, correto?
Então como você pode dizer que essa unidade pode ser um “caso de uso”?

Mas aí ja não é um teste unitário, ou a sua unidade não é caso de uso.

Eu estava me referindo a testes unitários e não a TDD em geral.

Não tem o mesmo efeito que você fazer o teste na tela. Se você vai fazer ou não, aí depende do nível de QA que você quer para o seu projeto\empresa.

Eu acho as ferramentas que automatizam o teste nas telas não são tão complicadas assim. Se bobear é quase tão simples como fazer um teste integrado na façade.

Não, não… imagina, não sou um fã de um “Unified Approach”, já trabalhei assi, e particularmente gosto muito de metodos ágeis e tento aplicar ao máximo no meu dia-a-dia - infelizmente as vezes não consigo por fatores externos a mim, mas no que depender de mim, eu uso agile, ou melhor, a minha visão de agile. É que eu só sou chato em fóruns, gosto de testar os argumentos apontados pela galera até o fim, estressar todas os fatores contra mesmo, as vezes eu vejo um post e tento pensar em todas as argumentações contra o que foi postado poderiam ser levantadas e faço um quote do post com elas. Acho que todos saem ganhando com isso quando há respeito. :slight_smile: E até me ajuda quando eu precisar defender os principios do Agile assim como você e o CV estão fazendo muito bem. :slight_smile:

Nesse caso em particular dos testes serem documentação de requisitos eu não concordo com você, embora eu ache que faça um certo sentido o que você esta querendo dizer.

O requisito deve dizer como o que o software deve fazer e como ele deve se comportar não vejo como, por exemplo, um diagrama de classes pode ajudar.
Vcoê pode conseguir essas informações juntando todos esses insumos aí que você mencionou, mas acho que aí você acaba perdendo a visão do todo.
Quanto a ficar destualizado, o teste pode ficar destualizado também, não? E em todo o caso, existem ferramentas que fazem rastreabilidade entre requisito e outros artefatos, como código por exemplo. Isso pode ajudar a equipe a manter todos os artefatos atualizados.

Pois é… acho que aí depende muito do cenário Rodrigo… sei lá, as vezes o próprio cliente exige isso, as vezes isso te salva-guarda na hora de uma negociação ou problema…

Pra dentro da minha façade tem um monte de objetos colaborando entre sí, porém, aquilo que realmente interessa para esse tipo de teste é o que oferece valor para o Ator. É um teste no código concentrado no objetivo do ator (caso de uso).

É possivel até usar um teste em código que valida e documenta um processo de negócio que envolva vários casos de uso (como exemplo posso encadear uma Suite do TestNG com vários testes concentrados nas façades).

O post todo é sobre TDD em geral.

Selenium ajuda bastante, mas ainda é ruim de manter e assertar (acho que essa palavra não existe, mas para uma madrugada de domingo pra segunda está muito bom). Para falar a verdade o problema maior é que numa aplicação Java a infra-estrutura para as coisas funcionarem dificulta enormemente o debug (o servidor demora quase 1 minuto pra subir e o turnaround é brochante). Não dá pra perder tempo com isso e você precisa dessa infra para automatizar o teste na tela.

Peraí, a alguns posts atrás você falou que a unidade do teste unitário poderia ser o “caso de uso” (você até colocou entre áspas, se não me engano).
Isso é errado, não tem o que discutir:

Case caso de uso? acho que você esta misturando as conversas :slight_smile:

De qualquer forma eu estava questionando:

  1. A possibilidade de usar teste unitário como documentação dos requisitos.
  2. A possibilidade de usar ferramentas que automatizam testes baseadas em GUI.

Não conheço selenium… só conheço silktest (por que será?) e não tenho dificuldades em assertar. Não sei se o selenium seria tão dificil assim, eu acho que não.

[quote=rodrigoy]
Para falar a verdade o problema maior é que numa aplicação Java a infra-estrutura para as coisas funcionarem dificulta enormemente o debug (o servidor demora quase 1 minuto pra subir e o turnaround é brochante). Não dá pra perder tempo com isso e você precisa dessa infra para automatizar o teste na tela.[/quote]
Mas você precisa ficar rodando o teste o tempo todo?
E olhe, eu não estou dizendo que você deve fazer teste em GUI em detrimento a testes unitários.

Sim - soh dar uma olhada nos exemplos de testes que o yoshi postou. Se um programador olhar pras assinaturas dos metodos e souber o que os testes estao tentando provar, ele tb entende os requisitos daquela unidade que esta sendo testada. Junta isso com uma ferramenta de cobertura e vc tb pode avaliar onde faltou teste ou onde fizeram gambiarras.

Selenium RC e WebDriver (que vai virar Selenium 2), fazem um trabalho bem decente na hora de testar interfaces Web, e sao super faceis de usar.

  1. Testes unitários documentam aquela unidade. A contrário do que a wikipedia diz você não está preso à classes ou funções, pode testar unitariamente um componente ou processo do seu sistema. Na verdade a maioria dos testes unitários tradicionais fazem isso.

  2. Para ter testes como documentação de requisitos funcionais você precisa trabalhar com testes funcionais, não unitários, automatizados. No meu projeto anterior tinhamos uma DSL em Ruby que guiava o Seleniume ia mais ou menos assim:


describe "A standard text search"do

  before :all do
   ingest_test_data
  end


 it "should display only results from a given state"do
  on SearchPage do
   search_for "automobile"
   filter_by :state => 'New South Wales'
  end

  on ResultsPage do
   entries.size.should eql(3)
   entries.each{|entry| entry.should be_an_ad_from('Victoria')}

   header.text.should eql("Results found for 'automobile' in 'New South Wales'")
   header.searchbox.contents.should eql("automobile ")
   header.filters.should be_filtering_by('New South Wales')
 end
end

Mas atualmente eu estou referindo o StoryRunner:

Scenario "file is already in registro's format" do
        Given "A file in Registro's format" 
        And "A parser for log files in DSL"
        When "Parser parses file"
        And "The resulting DSL lines are interpreted"
        Then "A timeline should be created with all entries in the file"
end

Serio que ha diferenca? So se for o numero de paginas. :slight_smile:

O que vc acha que é TDD então além de testes unitários guiando o desenvolvimento?

O que vc descreveu é sim teste unitario, da unidade facade.

O seu cliente entende alguma coisa nessa sua documentacao de requisitos? Ou é por isso que vc acha word uma alternativa viavel?

De uma olhada no FIT, acho que ele pode [editado] ajudar nessas situacoes.

O que eu acho que o mais importante sobre testes unitários é a possibilidade de fazer o teste de regressão de forma limpa e automática. Existe alguma coisa mais brochante que você entregar alguma correção/nova funcionalidade do sistema e surgir um problema novo ou já supostamente corrigido no passado? Isso gera um desgaste enorme.

Mas para isso o sistema deve ser coberto 100% por testes unitários e para isso o sistema deve nascer com testes unitários. É muito difícil você implementar teste em um sistema já existente. Mesmo porque para que um sistema seja bem testável sua arquitetura deve permitir isso.

E acredito também que os teste unitários para linguagens dinâmicas são imprescindíveis, pois você pode acabar com o seu sistema com apenas um erro de digitação de uma forma assustadoramente fácil.

Vejam bem, não que testes unitários sejam dispensáveis em linguagems compiladas, mas neste caso eu pego muitos erros de digitação em tempo de compilação, mas não todos :wink:

Na industria de qualquer coisa testes automáticos e garantia de qualidade são assuntos velhos velhos velhos.

Nos meados dos anos noventa eu trabalhava em uma empresa que fabricava máquinas para testar produtos fabricados por mais diversas industrias.
Pensando hoje, o que eles faziam era uma forma de teste unitário e teste funcional.
Teste unitário quando a máquina testava os componentes do sistema e teste funcional quando a máquina testava o produto como um todo.

Eu seja, estamos atrasados pra K C T :shock:

Phillip, não entendi algo na sua afirmação.
Até compreendo, via mocks, o teste sobre componentes. Mas quanto a processos fiquei um pouco confuso.

Nestes casos ( processos) o teste aplicado não deveria ser de “integração” ao invés de unitários ?

[quote=microfilo]
Pois é… acho que aí depende muito do cenário Rodrigo… sei lá, as vezes o próprio cliente exige isso, as vezes isso te salva-guarda na hora de uma negociação ou problema…[/quote]

Pode pegar QUALQUER cliente, de qualquer ramo, de qualquer projeto… pergunte para ele: Você quer ver um requisito implementado ou um requisito documentado? O que vc acha que ele vai responder?

Me parece que vocês entenderam mal o que o Dieval falou.

Eu li e reli o que ele escreveu e sou obrigado a concordar com quase tudo.
E muito do que ele falou não cai em contradição com o que vocês falaram.

Se testes unitários servem como documentação e são importantes no ciclo de desenvolvimento, então eles devem ser tratados como artefatos importantes. Ele criticava justamente a postura de várias empresas de jogar os testes para os estagiários, acabarem com uma pilha de testes que não testam nada e não documentam nada. Pior do que isso, a empresa ainda usa esse teste praticamente inútil como “critério de qualidade”, na boa e velha filosofia de “passou no teste está ok”.

Nesse caso, escrever testes desse jeito não só é inútil como também uma perda de tempo. Se o trabalho desses estagiários estivesse sendo gasto em uma atividade mais útil (como até mesmo preparar café), a empresa já lucraria mais.

Um ciclo de desenvolvimento sério deve tratar o teste unitário de maneira séria. Deve se preocupar se ele realmente reflete os requisitos de negócios (quando esses requisitos podem ser testados de maneira unitária). Deve garantir que o desenvolvedor entre em contato com o teste e corrija o código (ou muitas vezes o teste). O time também deve ter a preocupação de, em caso de um erro descoberto, corrigir o teste antes do código.

E em parte eu também concordo com o fato de que numa equipe experiente a validade do teste unitário cai um pouco. A equipe experiente refatora bem, modula bem, costuma a testar asserções, exceções e preocupa-se com diversas situações de erro naturalmente. Entretanto, a equipe experiente valoriza o teste unitário e sabe seu valor antes uma refatoração.

Em resumo, não adianta fazer teste para inglês ver. Mas também não adianta cair no conto da carochinha dos vendedores de JUnit e começar a achar que o teste unitário é a solução dos problemas, que ele vai mudar a forma dos seus programadores pensarem e que basta te-los para se ter qualidade. Eles são bons? Sem dúvida? Importantes? Muito. Mas são só mais uma das partes do ciclo de desenvolvimento, que tem várias.

O que eu discordo do Dieval é que acho que numa equipe experiente a importância do teste unitário cai um pouco, mas não muito. Seria o suficiente para arriscar um módulo do sistema sem eles em caso de pressa, e faze-los depois, só depois da release sair. Eu não reduziria ele a percentuais tão baixos. Agora, não dá para só bater em cima dessa tecla, sem levar em conta todo o resto que ele falou, que achei extremamente válido.

Em TDD, para implementar um caso de uso você roda os testes umas 200 vezes. Você roda os testes umas 20 vezes por hora. É importante que os testes rodem rapidamente. O Feedback tem que ser rápido.

[quote=microfilo][quote=peczenyj]
Exceptions que dependam de banco de dados ou outra parte do sistema, por exemplo.
Rotinas assincronas, recebimento de email, etc.
[/quote]
Hum, é verdade, mas dependendo da ferramenta que você esa utilizando, você pode fazer o script de teste da GUI fazer essas verificações também.[/quote]

Uma coisa é vc verificar se uma tela trata uma determinada exception. Outra é se as classes/métodos/funções tratam as exceptions de forma correta.

Não que o teste de GUI seja menos importante, ele é importante, mas vc precisa ter uma GUI para executa-lo, certo? Imagine que vc tem um bug de GUI que impossibilite que vc acesse 30% dos casos de teste – vc vai gerar um novo deploy e reiniciar o ciclo de testes depois de corrigido esse BUG? Quantos Bugs esse caso não ocultou?

[quote=microfilo][quote=peczenyj]
Nesse ponto vc pode fazer testes de integração de código. Vc faria com um framework de teste como o JUnit também.
[/quote]
É verdade, mas hoje existem ferramentas bem amigáveis para fazer teste automatizado baseado em GUI. As vezes fica até mais fácil que fazer com um JUnit da vida.[/quote]

Amigável significa trabalhar com record-playback com algum tipo de parametrização e/ou controle de transações? Pode ser muito bom para testes de regressão de código mas estamos falando de unidade. Dizer que uma ferramenta dessas é mais facil ou melhor que o JUnit é contra-produtivo pois o ideal é que ambas trabalhem juntas com objetivos diferentes.

Plugue uma ferramenta de cobertura de código como o EMMA e veja a porcentagem para ambos os casos. É absurdamente mais facil incrementar a cobertura com testes unitários (quando a arquitetura permite: quando não permite vc pode alterar a arquitetura), mas com testes de GUI vc vai chegar a um limite que, para ultrapassar, vai ter q adotar algum método invasivo (como injetar código de teste).

Felizmente o uso dessas duas abordagem pode maximizar a qualidade do software gerado. Entretanto qualidade é um termo subjetivo que normalmente reflete a opinião do cliente. De nada adianta uma montanha de testes se o software não faz o que o cliente quer.

[quote=xandroalmeida]O que eu acho que o mais importante sobre testes unitários é a possibilidade de fazer o teste de regressão de forma limpa e automática. Existe alguma coisa mais brochante que você entregar alguma correção/nova funcionalidade do sistema e surgir um problema novo ou já supostamente corrigido no passado? Isso gera um desgaste enorme.

Mas para isso o sistema deve ser coberto 100% por testes unitários e para isso o sistema deve nascer com testes unitários. É muito difícil você implementar teste em um sistema já existente. Mesmo porque para que um sistema seja bem testável sua arquitetura deve permitir isso.

Na industria de qualquer coisa testes automáticos e garantia de qualidade são assuntos velhos velhos velhos.

Nos meados dos anos noventa eu trabalhava em uma empresa que fabricava máquinas para testar produtos fabricados por mais diversas industrias.
Pensando hoje, o que eles faziam era uma forma de teste unitário e teste funcional.
Teste unitário quando a máquina testava os componentes do sistema e teste funcional quando a máquina testava o produto como um todo.

Eu seja, estamos atrasados pra K C T :shock:

[/quote]

Xandro, MUITO bem escrito e posicionado. Parabens. Realmente nada pior do que mais bugs na correcao de bugs existentes…

Se estou concentrando o teste na façade o teste é de integração, pois várias unidades estão sendo testadas em conjunto e o que eu quero com o teste é validar um objetivo do ator, e não um componente isolado. Prefiro fazer isso no código do que em artefatos fora dele. Esse é o ponto. É um teste de integração, no código e é TDD. TDD é um ciclo, é um método de se trabalhar, testes unitários e ferramentas só auxiliam nessa tarefa. Na TDD, a cada 3-5 minutos você tem um micro-requisito analisado, implementado e testado. O conjunto de micro-requisitos forma um requisito do usuário, como um caso de uso. Se alguém mandar um caso de uso aqui eu mando a classe de teste se alguém tiver mais alguma dúvida.

Documentos Words podem ser utilizados para ser entendível pelos usuários, mas na maioria das vezes, é melhor deixar os testes executáveis. Como falei, o cliente geralmente não entende QUALQUER documentação textual detalhada de requisitos. Isso é um trabalho seu, e não dele.

Com DSLs como o Phillip postou ou com o FIT dá pra fazer TDD com linguagem humana, aí passa a ser compreendido pelo stakeholder (o melhor dos mundos). Infelizmente em Java a DSL não é tão trivial, talvez em Groovy seja possível fazer algo parecido com o RSpec (nem sei se existe). BDD (entre outras coisas) é a evolução da TDD para vencer esse GAP e realmente a documentação de requisitos se tornar executável.

Há uns tempos atrás, li um artigo que questionava justamente essa afirmação. Veja bem, ele não era contra os testes unitários, e nem contra alterar a arquitetura. Mas o que ele questionava é até que ponto seria correto alterar a arquitetura para termos um JUnit?

Por exemplo, é prudente tornar um método que deveria ser privado “mais publico” só para testa-lo?

[quote=ViniGodoy]
E em parte eu também concordo com o fato de que numa equipe experiente a validade do teste unitário cai um pouco. A equipe experiente refatora bem, modula bem, costuma a testar asserções, exceções e preocupa-se com diversas situações de erro naturalmente. Entretanto, a equipe experiente valoriza o teste unitário e sabe seu valor antes uma refatoração.

Em resumo, não adianta fazer teste para inglês ver. Mas também não adianta cair no conto da carochinha dos vendedores de JUnit e começar a achar que o teste unitário é a solução dos problemas, que ele vai mudar a forma dos seus programadores pensarem e que basta te-los para se ter qualidade. Eles são bons? Sem dúvida? Importantes? Muito? Mas são só mais uma das partes do ciclo de desenvolvimento, que tem várias.

O que eu discordo do Dieval é que acho que numa equipe experiente a importância do teste unitário cai um pouco, mas não muito. Seria o suficiente para arriscar um módulo do sistema sem eles em caso de pressa, e faze-los depois, só depois da release sair. Eu não reduziria ele a percentuais tão baixos. Agora, não dá para só bater em cima dessa tecla, sem levar em conta todo o resto que ele falou, que achei extremamente válido.[/quote]

Alguns problemas de uma suite de testes com cobertura limitada:

Quem definiria o criterio para escrever ou nao um determinado teste?

Qual a vantagem de se ter uma suite incompleta, e portanto, que nao serve como testes de regressao (como bem lembrou o Xandro)?

editado: após reler o texto do ViniGodoy :oops:

Você realmente leu o que eu escrevi?

Como você modela dados nas aplicações que você faz? Os dados também não são requisitos? Se o cliente diz “o pedido de venda tem que ter um campo de observação” isso é um comportamento ou é um requisito que faz parte da visão estática do sistema? (leia meu artigo na MundoJava que será publicada neste mês sobre Domain-Driven Design)

Difícil… está no código e nunca é deixado pra trás. Se o requisito muda a primeira coisa que alteramos é a classe de teste. Entra no ciclo TDD. O código tem tendência a mostrar problemas mais facilmente. Documentos fora do código tendem mais a serem esquecidos.

Sim… e alguma vez você viu isso funcionando? Já tentou avaliar o custo benefício dessa abordagem? Já conseguiu fazer isso sem gastar centenas de milhares de dólares em ferramentas caras?

Há uns tempos atrás, li um artigo que questionava justamente essa afirmação. Veja bem, ele não era contra os testes unitários, e nem contra alterar a arquitetura. Mas o que ele questionava é até que ponto seria correto alterar a arquitetura para termos um JUnit?

Por exemplo, é prudente tornar um método que deveria ser privado “mais publico” só para testa-lo?[/quote]

Não estou entrando no mérito se é certo ou errado, mas o fato de que testar alguma coisa que não esta preparada para ser testável é muito dificil,na maioria das vezes impossível.

Sei, e defendo, que a industria de software é muito diferente das industrias “fisicas”. Mas vejam, em qualquer produto (televisão, carro, celular etc etc etc) tem pontos, as vezes circuitos inteiros, que servem apenas para testar o sistema. Então não vejo erro em alterarmos o software para ele ser testável.