Testes Unitários com Datas são muitas vezes tratados como um problema – considerando que não pode-se depender de uma data absoluta no caso de teste. Se o teste passar, então o teste será considerado bem-sucedido apenas para a respectiva data. Ao invés disso, o aconselhável é usar injeção de dependência (Adam Sroka, BigVisible):
Para testar uma série de datas interessantes você precisa aprová-las no cálculo. Assim, o método que faz o cálculo nunca deve receber a data por si mesmo – seja ela "now", ou recuperada do banco de dados, ou digitada pelo usuário, etc. Você deve obter a data em um nível superior e passá-la no seu cálculo.
É fácil ver como isso funciona nos Testes Unitários - mas a questão permanece: o que fazer nos Testes de Aceitação? Andreas Ebbert-Karroum enfrentou este problema e veio com uma lista de três alternativas:
- Em seus testes, faça que o resultado esperado também seja dependente de uma data/hora.
- Altere sua aplicação, para que ela não use a hora do sistema, mas um "time service", que você pode controlar remotamente para usar um hora diferente da hora do sistema.
- Altere remotamente a hora do sistema.
Gerard Meszaros, autor de Padrões de Teste xUnit, usa a segunda alternativa que também é conhecida como padrão "Virtual Clock":
Nós usamos uma camada de abstração sobre o serviço "real time" (leia-se: esconder as chamadas para a API "system time" por trás de uma interface) e depois substitua a implementação quando estiver testando por um controlável pelos scripts de teste. Por padrão, a implementação real é conectada.
Prós: Posso garantir que todas as condições são cobertos em cada teste. Pode ser usado para testar condições onde a hora está correndo.
George Dinwiddie, Chefe de Desenvolvimento de Software, também observa que utilizar uma única fonte para recuperar a hora evita problemas sutis com os sistemas que são executados em várias máquinas com múltiplas referências de tempo, ou seja, hora do sistema em úma máquina vs. hora do banco de dados em outra.
Ward Cunningham (wikipedia) tem uma abordagem diferente: "No framework "swim" testamos situações que duraram semanas. Nós escrevemos uma SQL com uma substituição global, $now, que deveria, no teste, acumular uma expressão que teria condições para cada avanço de tempo, seja horas, dias ou semanas. Tivemos a vantagem de ter uma ótima visualização quando rastreamos a SQL."
Mike Stockdale, desenvolvedor do FitSharp, aponta que apoia a análise relativa de datas, ex: hoje+2. Rick Mugridge, autor da FitLibrary, observa: "um gerador de data geral "DSL", que permite a seleção de datas relativas em fusos horários diferentes, oferecidos em diferentes formatos. Ele permite que as datas sejam selecionadas no final de um mês, em uma segunda-feira, etc. Isto tem sido utilizado amplamente em um sistema de reservas onde a seleção de datas no futuro é crítica, e onde os testes têm de fazer uso dos dados (e datas) que existem no sistema em teste." Enquanto Martin Gijsen, arquiteto de automação de testes, usa ANTLR para resolver o mesmo problema.
Assim ambas, a primeira e a segunda abordagem de Andreas estão em ampla utilização. Qual Abordagem que você utilizou? Quais são seus prós e contras?