Olá Pessoal, tudo bom?
O post de hoje continuará trabalhando com o código da conversão de datas que estamos tratando há algumas semanas. Nesse post iremos melhorar os testes unitários pois em nenhum teste unitários nós verificamos se a data convertida é igual a data original. Para isso precisaremos acrescentar mais um método de conversão, o que transforma uma instância de java.util.Date em uma String. Confira o post a seguir…
Pensando nos testes unitários…
Vamos analisar o código de um teste unitário, como está abaixo:
1 2 3 4 |
@Test public void testeOK() throws ParseException{ ConvertDate.parseDate("08/05/2016", ConvertDate.DateFormat.BR_FORMAT); } |
Bom a partir desse código para mim surgem algumas perguntas:
Primeira pergunta, esse teste realiza a verificação da Data convertida a partir da instância da String?
Segunda pergunta, como faremos essa verificação da instância de String com a instância de java.util.Date (a partir de agora chamarei de apenas Date) gerada?
Terceira pergunta, existe no JUnit alguma forma de comparar instâncias de String?
A resposta para a primeira pergunta é Não, esse teste não realiza nenhuma verificação da Data convertida. Para conseguir realizar isso, entra em pauta a resposta da segunda pergunta, teremos que construir um novo método que realiza a conversão de uma instância de Date em uma instância de String. Por fim a resposta da terceira pergunta é Sim, existem métodos especializados na biblioteca do JUnit que permitem realizar a comparação entre instância de String.
Bom, vamos começar então construindo um novo método para realizar a conversão de Date em String.
Novo método de conversão
Bom para criar o novo método iremos realizar uma cópia do método parse da classe ConvertDate. Só que ao invés de retornar uma instância de Date iremos retornar uma instância de String e o contrário para o parâmetro do método, Date ao invés de String. Conforme mostra o código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class ConvertDate { public enum DateFormat { USA_FORMAT("MM/dd/yyyy"), BR_FORMAT("dd/MM/yyyy"); private String format; private DateFormat(String format) { this.format = format; } public String getFormat() { return format; } } public static Date parse(String date, DateFormat formato) throws ParseException { if(date == null){ throw new ParseException("Deverá ser informada uma data a ser formatada", 0); } if(formato == null){ throw new ParseException("Deverá ser informado um formato de data para a formatação", 0); } SimpleDateFormat sdf = new SimpleDateFormat(formato.getFormat()); return sdf.parse(date); } public static String parse(Date date, DateFormat formato) throws ParseException { if(date == null){ throw new ParseException("Deverá ser informada uma data a ser formatada", 0); } if(formato == null){ throw new ParseException("Deverá ser informado um formato de data para a formatação", 0); } SimpleDateFormat sdf = new SimpleDateFormat(formato.getFormat()); return sdf.parse(date); } } |
Apenas com essas mudanças o erro de compilação que estava aparecendo na classe ConvertDate, de métodos duplicados, irá desaparecer. Mas agora irá aparecer um erro de compilação na linha 45, pois o que está sendo informado para o método parse, não é um parâmetro aceito pelo método, conforme API ((API método parse() classe SimpleDateFormat – Link))).
A classe SimpleDateFormat está na folha de uma hierarquia consistida por 4 classes, conforme podemos ver abaixo:
Como sabemos por Herança, os métodos da classe Superior podem ser acessados ou utilizados pelas instâncias. Dentro da classe Format existe um método chamado format() ((API do método format() classe Format – Link)). Esse método recebe uma instância de Object, assim será possível enviar um Date e ele irá formatar de acordo com o formato informado no construtor do SimpleDateFormat.
A forma de utilizar no código é basicamente igual ao método parse(), pois já estamos com o parâmetro aceito pelo método format correto, assim basta substituir na linha 45 para o método format que irá parar o erro de compilação, conforme código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class ConvertDate { public enum DateFormat { USA_FORMAT("MM/dd/yyyy"), BR_FORMAT("dd/MM/yyyy"); private String format; private DateFormat(String format) { this.format = format; } public String getFormat() { return format; } } public static Date parse(String date, DateFormat formato) throws ParseException { if(date == null){ throw new ParseException("Deverá ser informada uma data a ser formatada", 0); } if(formato == null){ throw new ParseException("Deverá ser informado um formato de data para a formatação", 0); } SimpleDateFormat sdf = new SimpleDateFormat(formato.getFormat()); return sdf.parse(date); } public static String parse(Date date, DateFormat formato) throws ParseException { if(date == null){ throw new ParseException("Deverá ser informada uma data a ser formatada", 0); } if(formato == null){ throw new ParseException("Deverá ser informado um formato de data para a formatação", 0); } SimpleDateFormat sdf = new SimpleDateFormat(formato.getFormat()); return sdf.format(date); } } |
Voltando a classe de teste…
Ao voltar ao código da classe Teste podemos ver que está ocorrendo um erro de compilação no método testeDataNula(). Esse erro ocorre pois ao passar uma instância null, esta pode ser uma String ou um Date e assim o javac não sabe qual método será chamado durante a execução. Nós vamos resolver esse erro em breve, não esquente com ele agora (A não ser que vc tenha TOC… aí não posso fazer nada… :-P)
Vamos então arrumar a casa. Primeiramente para cada método de teste vamos criar uma instância de String para substituir o valor que está sendo passado diretamente ao método parse, como mostram as linhas marcadas abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import org.junit.Test; public class Teste { @Test public void testeOK() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeDataNula() throws ParseException{ String dataString = null; ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeFormatoNulo() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, null); } @Test public void testeDataFormatoDiferentes() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, ConvertDate.DateFormat.USA_FORMAT); } } |
Você notou que o erro de compilação sumiu? É porque agora não estamos simplesmente passando um null do tipo Object, mas agora é um null do tipo String. Dessa forma o compilador Java sabe qual método parse você irá chamar. Continuando, para os métodos testeDataNula() e testeFormatoNulo() já está pronto as alterações. Agora é necessário focarmos nos dois métodos restantes. Para ambos vamos atribuir a uma instância de Date o retorno do método parse, como mostram as linhas no código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import java.util.Date; import org.junit.Test; public class Teste { @Test public void testeOK() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeDataNula() throws ParseException{ String dataString = null; ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeFormatoNulo() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, null); } @Test public void testeDataFormatoDiferentes() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.USA_FORMAT); } } |
Essa instância de Date será utilizada agora, pois iremos chamar o novo método parse criado no tópico anterior. Já iremos aproveitar e atribuir o retorno deste método a uma instância de String, para podermos realizar as comparações depois. Veja no código abaixo as novas linhas criadas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import java.util.Date; import org.junit.Test; public class Teste { @Test public void testeOK() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); String dataReconvertida = ConvertDate.parse(date, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeDataNula() throws ParseException{ String dataString = null; ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeFormatoNulo() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, null); } @Test public void testeDataFormatoDiferentes() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.USA_FORMAT); String dataReconvertida = ConvertDate.parse(date, ConvertDate.DateFormat.BR_FORMAT); } } |
Com o código construído acima nós ainda não respondemos concretamente nenhuma das três perguntas citadas acima, mas com o próximo tópico podemos responde-las.
Adicionando as validações do JUnit
O JUnit possui uma série de mecanismos para validarmos se determinada instância está com valores ou estados corretos, ou ainda, de acordo com o que desejamos para o teste. Esses métodos são estáticos e se encontram dentro da classe org.junit.Assert. Se você está usando uma versão mais antiga do JUnit para realizar os testes essa classe pode não existir, pois existirá uma classe junit.framework.Assert, que na atual versão está depreciada.
Essa classe Assert contém vários métodos mas iremos utilizar dois deles aqui o assertEquals(Object, Object) ((API do método assertEquals da classe org.junit.Assert – Link)) e o método assertNotEquals(Object, Object) ((API do método assertNotEquals da classe org.junit.Assert – Link)). O primeiro verifica se as instâncias de Object passadas são iguais, utilizando o método equals() da classe correspondente. O segundo é o contrário do primeiro.
Dessa forma iremos utilizar o assertEquals() no método testeOK() e o segundo no método testeDataFormatoDiferentes(). Para utilizarmos é necessário importar a classe org.junit.Assert, conforme mostra o código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package br.com.mauda.exemplos.dates.versao7.exemplo001.v3; import java.text.ParseException; import java.util.Date; import org.junit.Assert; import org.junit.Test; public class Teste { @Test public void testeOK() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); String dataReconvertida = ConvertDate.parse(date, ConvertDate.DateFormat.BR_FORMAT); Assert.assertEquals(dataString, dataReconvertida); } @Test(expected=ParseException.class) public void testeDataNula() throws ParseException{ String dataString = null; ConvertDate.parse(dataString, ConvertDate.DateFormat.BR_FORMAT); } @Test(expected=ParseException.class) public void testeFormatoNulo() throws ParseException{ String dataString = "08/05/2016"; ConvertDate.parse(dataString, null); } @Test public void testeDataFormatoDiferentes() throws ParseException{ String dataString = "08/05/2016"; Date date = ConvertDate.parse(dataString, ConvertDate.DateFormat.USA_FORMAT); String dataReconvertida = ConvertDate.parse(date, ConvertDate.DateFormat.BR_FORMAT); Assert.assertNotEquals(dataString, dataReconvertida); } } |
Nesse momento se você rodar a classe de Teste novamente via JUnit verá que todos os testes funcionaram corretamente, só que desta vez seu teste unitário está mais robusto e validando as três perguntas feitas no começo deste post. Assim você tem a plena certeza que a classe de ConvertDate está realizando um trabalho correto. Isso ajuda a evitar erros relacionados a essa classe durante a utilização desta em um projeto.
Lembrando que todos os códigos acima, para facilitar estão disponíveis no projeto Exemplos no Repositório Git do Bitbucket. Se você não sabe como clonar um repositório, veja meus tutoriais Versionamento Git na IDE Eclipse.
finnaly{
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Leave a Reply