Olá Pessoal, tudo bom?
Neste artigo iremos apresentar um pouco sobre a ferramenta de debug na IDE do Eclipse. Essa é uma ferramenta extremamente importante no dia a dia para a identificação mais rápida de valores internos de atributos de instâncias de classes. Para quem está começando agora no mundo do desenvolvimento ter uma ferramenta como Debug ajuda na compreensão de muitos aspectos da linguagem.
O que é Debugging???
É uma forma de verificar valores e condições de instâncias de classes e atributos em tempo de execução. Isso ocorre através da verificação de certas linhas de código através de breakpoints. Além disso é possível criar pontos de inspeção (watchpoints) para determinados atributos e classes.
Preparando o Ambiente…
Para que você possa acompanhar com detalhes esse tutorial de Debug você deverá realizar o fork de algum projeto do meu repositório do Bitbucket, dentro do Eclipse. Não lembra o que é clonar? De uma olhada nesse tutorial na parte de Configuração do Bitbucket na IDE Eclipse.
Após a clonagem, você deverá importar o projeto para dentro do seu workspace, conforme esse tutorial, parte de Importando o projeto para o Eclipse.
Com isso você estará com o projeto pronto para realizar esse tutorial sobre Debug na IDE Eclipse.
Criando Breakpoints
O aspecto básico de qualquer processo de Debug de código fonte é a criação de Breakpoints ou em bom português Pontos de Parada. Um breakpoint como a tradução diz é um ponto em uma linha de código o qual o seu processo de debug irá parar se a execução do código chegar até esse ponto.
Para começar esse tutorial vamos abrir a classe TesteArtistaModel.java e vá para a linha 93. Para inserir um breakpoint em um código Java é necessário ir até o canto esquerdo da tela e na coluna ao lado do código da linha desejada dar um duplo clique para aparecer uma bolinha azul. Essa bolinha é o breakpoint, como mostra a Figura 01. É possível também inserir um breakpoint em uma linha clicando sobre ela e acionando o atalho Ctrl + Shift + B.
Rodando…
Agora é necessário rodar o programa em modo debug, para isso clique com o botão direito sobre a classe e vá em Debug as… > JUnit Test, pois é uma classe de teste JUnit, conforme mostra a Figura 02.
Ao rodar em modo Debug, o Eclipse pedirá para você ir para a perspectiva de Debug, conforme mostra a Figura 03.
Clique no botão Yes para que o eclipse abra a perspectiva de Debug, com a linha do breakpoint em verde como mostra a Figura 04
Caso você passe o mouse sobre o atributo artista deverá, após alguns segundos, aparecerá os valores referentes ao atributo conforme mostra a Figura 05.
Como pode ser visto, o atributo id está nulo e o atributo nome possui o valor de Francis Bacon. Ainda é possível identificar que o id em memória do Java é 39. Esse é o valor do endereço de memória que o atributo se encontra. Agora vamos começar a explorar as funcionalidades principais que o Debug nos proporciona para o avanço sobre o código.
Funcionalidades de Avanço no Código
Existem 5 funcionalidades de avanço de código, os quais estão representados numerados na Figura 06.
- Funcionalidade de Resume (F8) – Avança para o próximo Breakpoint do código. Caso não tenha próximo, avança até o fim da execução do software.
- Funcionalidade de Terminate (Ctrl + F2) – Finaliza a execução do software independente de onde esteja
- Funcionalidade de Step Into (F5) – Entra dentro de um método que exista na linha da execução. Muito importante para saber para onde o sistema está indo
- Funcionalidade de Step Over (F6) – Avança para a próxima linha de código dentro da mesma classe que está em execução.
- Funcionalidade de Step Return (F7) – Volta para o método anterior. Fácil de ser verificado pela stack de execução.
Para testarmos cada um desses pontos vamos ir realizando algumas operações, mas vamos abrir a view do JUnit para que possamos verificar o que está acontecendo nos testes unitários. Para acessar essa view, acesse o menu Window > Show View > Other… e na popup Show View que aparecer escolha a opção JUnit, conforme Figura 07.
Funcionalidade Resume F8
Observe como está o seu Teste JUnit, provavelmente esteja no meio da primeira execução. Então pressione a tecla F8, ou clique no botão marcado com 1 na Figura 06. Provavelmente a tela piscará e ele voltará com uma linha verde para a mesma linha que já estava antes, como mostra a Figura 08.
Mas repare que houve a execução completa de um teste JUnit, onde agora na view JUnit está aparecendo a segunda execução (Runs 2/7), conforme está sendo mostrado pela Figura 08.
Dessa forma é fácil entender que a função do F8 é avançar para o próximo breakpoint, para continuar a execução do programa. Vamos agora colocar um outro breakpoint para que isso fique claro. Abra a classe Artista e no método getNome() coloque um breakpoint na única linha do método, conforme Figura 09.
Agora pressione F8. Provavelmente a linha verde irá parar nesse novo breakpoint da Figura 09. Se você pressionar novamente F8, ele voltará para o breakpoint da classe TesteArtistaModel. Isso se estenderá até o fim da execução do teste JUnit.
Funcionalidade Step Into (F5) e Step Return (F7)
Agora vamos abrigar em um outro tópico as funcionalidades de Step Into e Step Return. Não desfaça os dois breakpoints criados nas classes de TesteArtistaModel e Artista. Agora inicie novamente um debug da classe de TesteArtistaModel, ele irá parar no primeiro breakpoint, conforme Figura 10.
Pressione a tecla F5, o Eclipse irá abrir uma classe org.junit.Assert, onde não aparecerá o código da classe, indicando que o projeto não possui o código fonte dessa classe, conforme Figura 11. O que aconteceu?
Repare qual era a linha que estava sendo executada pelo debug:
1 |
Assert.assertNotNull(artista); |
Dessa forma a execução do Java entrou no método assertNotNull(artista) da classe Assert! Como posso provar isso, observe na parte superior da tela existe uma View chamada Debug, nesta view possui uma stack de execução. Qual é o método que está em execução no momento? Assert.assertNotNull(Object) line: 631. Assim a funcionalidade do Step Into (F5) possui a caracteristica de, como nome diz, entrar dentro de um método, não importa se você possua o código ou não.
Agora pressione F7, a funcionalidade de Step Return. O que aconteceu? Veja na Figura 12:
Ele voltou para o penúltimo método da stack avançando para a próxima linha da classe TesteArtistaModel. Logo a funcionalidade da tecla F7 retorna para o método anterior da stack trace. Repare que ele voltou para a linha:
1 |
Assert.assertFalse(artista.getNome().isEmpty()); |
Uma linha após a linha que havia sido iniciado a funcionalidade com o F5. Clique novamente na tecla F5, para onde a execução foi? Ele entrou dentro do método getNome() da classe Artista. Pressione novamente F5, para onde ele foi? Ele voltou para a mesma linha da classe TesteArtistaModel, apresentada no código acima. E agora se você acionar novamente F5, o que aconteceria?
Ele foi para um código que você não possui as linhas de código, mas repare na stacktrace na View Debug, ele está dentro do método isEmpty() da classe String. O que está acontecendo aqui?
Sempre que você aciona a funcionalidade Step Into (F5), ele entra dentro do método.
Agora vamos examinar a linha atual que ele se encontra:
1 |
Assert.assertFalse(artista.getNome().isEmpty()); |
Quantas chamadas a métodos temos aqui? Para responder isso vamos dividir cada chamada em linhas. O primeiro ponto a ser executado é sempre o mais interno. Logo é o método artista.getNome() que pode ser dividido no seguinte código:
1 2 3 |
String nome = artista.getNome(); Assert.assertFalse(nome.isEmpty()); |
O próximo passo resolver o método nome.isEmpty(), conforme o código abaixo:
1 2 3 4 5 |
String nome = artista.getNome(); boolean nomeIsEmpty = nome.isEmpty(); Assert.assertFalse(nomeIsEmpty); |
Existe mais alguma chamada de método? Não! Logo essa linha de código chama 3 métodos diferentes. Assim cada vez que a funcionalidade Step Into é chamada ela vai adentrando dentro dos métodos, até acabar a execução daquele método aí volta para o método anterior da stack. Se for uma linha composta por vários métodos ela vai “resolvendo” esses métodos do mais interno para o mais externo.
Funcionalidade Step Over (F6)
Se a Step Into entra dentro dos métodos, a Step Over passa pela linha de métodos completamente. Vamos executar mais uma vez em debug a classe de teste TesteArtistaModel. Novamente paramos no breakpoint da Figura 13
Pressione a tecla F6, Step Over. O método passará para a próxima linha da classe TesteArtistaModel, representado na Figura 14.
Pressione novamente o botão F6. Ele foi para a próxima linha da classe TesteArtistaModel?
1 |
ArtistaEnum artistaEnumTemp = ArtistaEnum.getArtista(); |
Não. Ele foi para o método getNome() da classe Artista! Mas ao acionar a funcionalidade Step Over ele não iria para a próxima linha? Sim e não! Sim porque é isso que a funcionalidade deve fazer, MAS, se houver um breakpoint no meio da execução dessa linha… A execução será parada nele. Logo por esse motivo ele parou no método getNome().
Parando a execução de um código (Terminate)
É possível encerrar a execução de um código utilizando a funcionalidade Terminate. Para isso, basta apertar o botão de Stop, quadrado vermelho indicado pelo número 2 da Figura 15. Ele irá terminar a execução daquela instância da JVM.
Verificando o valor de um código
Ao estar no modo Debug, é possível avaliar dinamicamente valores de variáveis conforme já foi mostrado em alguns parágrafos atrás. Mas é possível avaliar expressões de um código?. Por exemplo, seria possível avaliar se a expressão artista.getNome().isEmpty() retorna um valor falso?
Sim isso é possível através da funcionalidade Inspect. Inicie novamente um teste da classe TesteArtistaModel no modo Debug e selecione a linha artista.getNome().isEmpty(), conforme mostra a Figura 16
Agora pressione as teclas Ctrl + Shift + I ou clique com o botão direito do mouse sobre a minha selecionada e vá na opção Inspect. Ele cairá no breakpoint do método getNome(). Isso serve para mostrar que independente da ação realizada ao estar no modo Debug um breakpoint sempre será ativo. Pressione F8 para continuar a execução do Inspect o resultado está mostrado na Figura 17.
A expressão indica que o valor é falso, logo existe alguma String não vazia dentro do atributo nome. Mas qual é o nome? É possível determinar pela funcionalidade de Inspect? Sim, é possível. Vamos selecionar novamente a expressão, mas agora removendo a parte do isEmpty(), ou seja, selecionando a linha artista.getNome() somente. O resultado você confere na Figura 18:
A funcionalidade de Inspect é muito poderosa, pois permite a avaliação de expressões em tempo de execução de código. Dessa forma, quando você estiver com dúvidas do que um determinado método irá retornar, recorra a funcionalidade do Inspect. Ela irá auxiliar a sua tomada de decisão para saber se um código está correto.
finally{
Existem outras opções e funcionalidades do debug que irei apresentar no decorrer das semanas em posts aqui no site. Mas esse básico é muito importante para que você aprenda a utilizar esta ferramenta que é muito utilizada no dia a dia de qualquer desenvolvedor de software Java
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!
Stas says
Meu depurador de PHP favorito é Codelobster – http://www.codelobster.com
Mauda says
Olá Stas, tudo bom?
Meu conhecimento sobre PHP é bem limitado, mas obrigado pela dica!
Obrigado!
erick says
Muito obrigado, esse artigo me ajudou demais
Mauda says
Olá Erick, tudo bem?
Que bom que auxiliou seu caso.
Precisando estamos por aqui.
Obrigado.