rvf, software e mitos

Posts Tagged ‘tdd

como já diria Joel Spolsky… este blog já está fedendo a cupim (não, Joel não disse isso, na verdade do que se trata dele terminou nas reticências e tinha a ver com o titulo do post) mas tudo bem, esta é uma rapidinha que, se eu tivesse um numero consideravel de seguidores no twitter, seria um twitt… mas, como eu não gosto do twitter e nem quero que você me siga, vai pra cá mesmo.

Tudo que você faz, o faz como se você mesmo fosse usar? Pense nisso antes de construir a próxima linha de código lá no seu trabalho, esqueça seu chefe chato (não que o meu seja, caso o mesmo leia este post…) e codifique como se você mesmo fosse seu próprio usuário, como se você dependesse do seu próprio sistema para realizar seu trabalho.

Afinal de contas meu caro colega, os usuários gostariam tanto, mas tanto, que o que tu faz realmente funcionasse, que eles seriam capazes de te dar um beijo nas nadegas a cada dia de caixa fechado sem bug no sistema. E eu, sendo o cara que irá dar manutenção no seu código, adoraria tanto ver uma suite de testes unitários bem construidos quando o pegasse, que seria capaz de.. te pagar uma Polar bem gelada no boteco mais badalado da cidade baixa aqui de POA.

“Ah, mas eu já escrevo todo aquele código e testo tudo no main..  ainda tenho que escrever testes unitários pra ele?” Amigão, se tu quiser não precisa mais escrever este código todo.. escreva apenas os testes então. Ééé, isso mesmo. Esqueça aquela coisa toda logo de cara e vá direto aos seus @Test.. apenas coloque na cabeça: só entregue este código depois que os testes passarem! Se por acaso, tu ter que codificar um pouco para os testes passarem, beleza, tu faz classe a classe, mas espere, a classe não precisa existir para tu escreve-la pela primeira vez no seu teste… deixe o Eclipse chorar mesmo, só depois tu cria, ou melhor, rode a droga do teste sem a classe, para tu VER na tela que nada funciona sem a presença da maldita classe. É bem simples, não precisa ler um livro para começar.. são regrinhas básicas: da direita (seus testes) <simula erro> para a esquerda (implementação de uma pequena porção de código) <testa>.

“Mas quando eu sei que não preciso mais testar?” Quem disse que não precisa mais testar? Sempre que tu tocar aí tu vai testar, a unica diferença é que não precisará mais se preocupar com o que já está testado, pois se der algum tipo de erro, tu saberá exatamente onde consertar. Eu mesmo, sei quando não preciso mais testar quando o código que eu preciso para entregar a minha estória está pronto e é suficiente, pois de acordo com o TDD, se ele já está pronto, é porque existe um teste para ele!

Finalizando.. “eat your own dog food” .. estou ficando louco ou:

a propósito (falando em loucos), aproveitando a presença do Rod Johnson na TDC, nos diga Rod: o que faz a SpringSource, usar PHP no seu portal? http://www.springsource.com/index.php, Por quê não o nosso amigo SpringMVC?

E que calor infernal em Porto Alegre…

Não, eu não sou nenhum guru em TDD, mas aos poucos estou notando a vantagem desta técnica que agrega muito mais do que simples junits ao seu projeto. TDD te fornece na verdade outra abordagem: o desenho do seu software de uma maneira mais desacoplada e coesa.

... um pouco de história: Era uma vez um jovem desenvolvedor empolgado em introduzir técnicas de testes ágeis em sua empresa, porem, foi barrado pelo seguinte motivo: Testes (senão, os feito por testadores) são uma segunda opção (precisa dizer que a primeira é o cronograma?).  Esta é a visão dos gerentes/gestores de projetos que não conhecem TDD. A única coisa que sabem a respeito é de que TDD se testa primeiro. Na verdade, alguém que pensa assim, não sei nem como chega a este raciocínio, pois duvido muito que eles entendam o que dizem -i.e. como assim testar primeiro algo que ainda nem existe?-

TDD, não deve ser considerado como uma prática de teste -apenas-, mas sim como uma técnica poderosa de desenho/construção de aplicações OO, E, DE QUEBRA, tu ganhas o teste de unidade. Simples assim. Para cada caso, um teste que falha, onde sua história só termina quando ele passa. Por completo! A principio a idéia parece um pouco radical, mas é isso mesmo: você deve construir um teste que falhe primeiro, (nem que seja para testar se o seu JUnit está presente no seu classpath!), para, então, você ir incrementando aos poucos, refatorando, e criando as classes, métodos, xpto…  que sejam necessários para o mesmo passar e testando. Vamos brincar com  isso em um exemplo simples, de Conta Corrente:

Criamos um novo projeto, e nele, um novo teste unitário (estou utilizando o JUnit 4):

package com.wordpress.robsonvf;

import org.junit.Assert;

import org.junit.Test;

public class ContaCorrenteTest {

@Test

public void umDepositoDeveAumentarOSaldoNoValorDoDeposito() {

Assert.assertTrue(false);

}

@Test

public void umSaqueDeveDiminuirOSaldoNoValorDoSaque() {

Assert.assertTrue(false);

}

@Test(expected=RuntimeException.class)

public void umSaqueSoEhPossivelSeTemSaldo() {

}

}

Esta é a abstração mais simples possível de conta corrente que consegui chegar, creio que para o exemplo seja suficiente. Rode este teste, e veja-o falhar descaradamente e sem dó: o primeiro passo rumo a TDD foi dado. O segundo é fazer isso tudo funcionar! Notaram que, quando eu disse “abstração mais simples possível de conta corrente” ficou claro que, eu comecei a desenhar meu software antes mesmo de criar uma única classe de negócio sequer? E ainda tem gente que duvida que simples testes unitários são tão claros quanto montanhas de documentos.

Vamos trabalhar então no método: umDepositoDeveAumentarOSaldoNoValorDoDeposito, o que este método precisa para viver numa conta corrente? Na minha abstração primária, ficou assim:

@Test

public void umDepositoDeveAumentarOSaldoNoValorDoDeposito() {

ContaCorrente cc = new ContaCorrente(200d);

double saldo = cc.getSaldo();

cc.deposita(100d);

Assert.assertTrue(saldo+100d == cc.getSaldo());

}

Precisa explicar? uma nova sessão de conta corrente, um registro histórico do saldo atual com o qual a conta foi criada, um deposito, e uma verificação: o saldo esperado é igual ao saldo da conta? Você já consegue rodar este teste? Não? Está esperando o que então para criar a classe ContaCorrente e os métodos que o sua IDE chora sem parar por eles não existirem? Se utiliza o eclipse/netbeans, basta ir clicando nos erros e gerando a classe, construtores, métodos…, faltaria só implementar. Este é o seu exercício antes de continuar com a leitura.

Implementou? Rode o teste agora. Passou? Ótimo! Seu primeiro teste usando TDD foi concluído com sucesso. Se quiser, faça isso com os outros métodos até todos passarem. (recomendo fazer isso antes de ver, logo abaixo, o restante do código).

O teste pronto:

package com.wordpress.robsonvf;

import junit.framework.Assert;

import org.junit.Test;

public class ContaCorrenteTest {

@Test

public void umDepositoDeveAumentarOSaldoNoValorDoDeposito() {

ContaCorrente cc = new ContaCorrente(200d);

double saldo = cc.getSaldo();

cc.deposita(100d);

Assert.assertTrue(saldo+100d == cc.getSaldo());

}

@Test

public void umSaqueDeveDiminuirOSaldoNoValorDoSaque() {

ContaCorrente cc = new ContaCorrente();

cc.deposita(100);

cc.saque(90d);

Assert.assertTrue(10 == cc.getSaldo());

}

@Test(expected=RuntimeException.class)

public void umSaqueSoEhPossivelSeTemSaldo() {

ContaCorrente cc = new ContaCorrente();

cc.deposita(200);

cc.saque(201);

}

}

A minha classe ContaCorrente (aposto que a sua ficou igualzinha!):

package com.wordpress.robsonvf;

public class ContaCorrente {

private double saldo;

public ContaCorrente() { }

public ContaCorrente(double d) {

this.saldo +=d;

}

public double getSaldo() {

return this.saldo;

}

public void deposita(double d) {

saldo +=d;

}

public void saque(double d) {

if ((saldo-d) < 0)

throw new RuntimeException(“Saldo insuficiente!”);

saldo -= d;

}

}

Aprimore mais a lógica de negócio desta classe, envolva outras classes, e não se esqueça: primeiro o teste, depois a especificação do negócio, e por fim, a implementação… E FUNCIONANDO…

Este post foi apenas um simples estimulo para quem está querendo aprender TDD, assim como eu. Espero que você adote esta pratica para seus novos algoritmos, e, que convença seu chefe de que TDD não é apenas teste unitário avulso, mas, sim, uma nova maneira de se pensar na hora de sair construindo software.

Até a próxima.. e que venha a Agile Weekend aqui em poa 🙂



  • Nenhum
  • Adolfo: Muito bom este post. Acho que tudo isso pode ser resumido em uma única palavra: humildade (isso não significa não defender seu ponto de vista).
  • Adolfo: Olá Robson, Alguns modelos até consegui identificar em alguns projetos que já trabalhei... Com algumas coisas eu concordo e outras não... Q
  • milah: Eu tenho um Amazon L71. Até 2 meses atrás não tive problemas com ele. Já troquei a placa de lan dele, por uma que capta melhor wi-fi. Só que ago