Exemplo TDD, parte 3: corrigindo bugs
Publicado por Ivan Sanchez em Sexta-feira, Dezembro 1, 2006
Ao final da segunda parte do nosso exemplo, terminamos com a seguinte lista de implementação:
Representar hora no formato hh:mmPermitir a criação de uma hora padrão (”00:00?)Não permitir que se crie hora fora do formato hh:mm- Pode haver uma hora do tipo h:mm
- Pode representar horas acima de 23:59, então uma hora como 300:00 é válida
- Horas negativas são válidas
- Deve ser possível fazer soma de horas
Vamos resolver o primeiro item que levantamos agora, mais uma vez partindo de um novo teste:
public void testCriacaoHoraNoveEMeia()
{
Hora hora = new Hora("9:30");
assertEquals("9:30", hora.toString());
}
Ao rodar este teste ele esbarra na validação que criamos anteriormente:
java.lang.RuntimeException: Formato de Hora inválido: 9:30
Como isso não deveria acontecer, mudamos a nossa expressão regular:
if (!string.matches("[0-9]*:[0-9][0-9]"))
Todos os testes passam, e podemos passar para nossa próxima tarefa que é representar horas maiores que 23:59. Fazemos isso com mais um teste:
public void testCriacaoHoraCentoETrinta()
{
Hora hora = new Hora("130:00");
assertEquals("130:00", hora.toString());
}
Rodamos o teste e ele passa sem nenhuma mudança no código. Isso significa que o nosso item da lista já estava funcionando.
Neste ponto um outro programador que já usando nossa classe em outra parte do sistema afirma: “tem um problema com esse código! Parece ser possível criar uma hora sem definir a quantidade de horas (“:15″), o que vai contra nossa definição mínima de hora como h:mm”. Como não pretendemos mudar o formato da hora e outras partes do sistema já estão usando validação, esta nova possiblidade tornou-se um problema. E agora?
Corrigir bugs com TDD não é diferente de implementar qualquer outra funcionalidade. Basta ficar atento para não implementar a correção sem a criação de um teste antes. A definição deste teste permite a descrição e a reprodução exata do problema, e cria uma validação em código que garante que o erro não voltará a ocorrer.
Então vamos partir para a correção, escrevendo um teste que especifique o problema:
public void testCriacaoHoraSohComMinutos()
{
try
{
new Hora(":15");
fail("uma hora não pode ser criada só com minutos");
} catch (RuntimeException e)
{
assertEquals("Formato de Hora inválido: :15", e.getMessage());
}
}
O teste falha, confirmando as suspeitas de que algo não está como deveria:
junit.framework.AssertionFailedError: uma hora não pode ser criada só com minutos
Não resta nada a fazer a não ser refinar nossa expressão regular:
if (!string.matches("[0-9][0-9]*:[0-9][0-9]"))
Com esta mudança todos os testes passam mais uma vez. Perceba que independente do que estamos implementando (correção ou nova funcionalidade) o processo é sempre o mesmo. Então restam os seguintes itens na nossa lista:
Representar hora no formato hh:mmPermitir a criação de uma hora padrão (”00:00?)Não permitir que se crie hora fora do formato hh:mmPode haver uma hora do tipo h:mmPode representar horas acima de 23:59, então uma hora como 300:00 é válidaNão pode haver hora definida apenas com minutos (“:15″)- Horas negativas são válidas
- Deve ser possível fazer soma de horas
Até a próxima!
Alexandre disse
Muito bom amigo, sei que o post nao é recente mais a sua ideia é show…
Como fazer para testar list e object vindo do hibernate?
E como fazer teste em frameworks web? uso o Mentawai.
Testa servlets eu ja vi como aqui mesmo no seu blog!!!
Ivan Sanchez disse
Olá Alexandre!
Para testar objetos vindo do Hibernate você pode usar o DBUnit, que permite que o banco de dados esteja num estado conhecido antes de cada teste. Vale lembrar que este é um teste de integração, mas também é válido para desenvolver usando TDD.
Já para frameworks web em geral você pode usar o EasyMock para testar a comunicação da sua classe com o framework. Infelizmente não possuo muita experiência com o Mentawai, mas sobre mocks você pode ler aqui.
Espero ter ajudado
Diego Pires Plentz disse
Da pra melhorar o teste usando a seguinte regular expression:
if (!string.matches(“[0-9]{1,}:[0-9]{2}”))
Ou seja, requer no mínimo 1 dígito no primeiro match e precisa de exatamente 2 dígitos no segundo.
Ivan Sanchez disse
Legal, Plentz
Na próxima parte do exemplo sua sugestão já vai entrar como um refactoring …
Mark disse
Thank You