O documento fornece uma introdução aos principais frameworks e documentação sobre logging e testes de unidade em Java, incluindo Apache Log4j e JUnit. Ele discute tópicos como configuração, níveis de log, appenders, layouts no Log4j e tipos de testes, como usar JUnit 4, asserções e anotações.
2. Apache Log4j
Tópicos
• Logging • BasicConfigurator
• Antes do Log4j • PropertyConfigurator
• Exemplo de API de Logging • DOMConfigurator
• Log4j • Performance
• Eventos de Log • Hierarquia de Loggers
• Logger
• Level
• Exemplo
• Appenders & Layouts
• Appenders Disponíveis
• Layouts Disponíveis
• PatterLayout
• Configuração
3. Logging
• “Diário de bordo”
Histórico de execução
• Depuração
Vantagens
Instruções persistentes
Sessões persistentes
Multithreading
Procedimentos recursivos
4. Antes do Log4j
public static void main (String[] args) {
System.out.println(“Vai executar o main: args = ” + args);
//...
}
private static final boolean DEBUG = true;
public static void main (String[] args) {
if (DEBUG) {
System.out.println(“Vai executar o main: args = ” + args);
//...
}
}
5. Exemplo de API de Logging
public class Log {
protected static java.io.PrintStream stream;
protected static boolean enabled = true;
public static void print (Object o) {
if (enabled)
stream.println(o.toString());
}
}
public static void main (String[] args) {
Log.print(“Vai executar o main: args = ” + args);
}
6. Log4j
• Projeto da Apache
http://logging.apache.org/log4j/
• API de Logging
Categorias de logging
Níveis (prioridades)
Formatação dos eventos de logging
Saídas para os eventos de logging
Informações de Contexto
Configurável
7. Eventos de Log
• Horário
• Prioridade
• Categoria
• Mensagem
• Arquivo fonte
• Número da linha
• Nome da thread
• ...
8. Logger
• Gerador de eventos de logging
org.apache.log4j.Logger
• Categorias de logging
• Criando um Logger
Logger log = Logger.getLogger(“categoria”);
Logger log = Logger.getLogger(AClass.class);
9. Level
• Prioridade de Logging
Constantes definidas em org.apache.log4j.Level
DEBUG < INFO < WARN < ERROR < FATAL
• Emitindo mensagens
log.debug(“mensagem”);
log.info(“mensagem”);
log.warn(“mensagem”);
log.error(“mensagem”);
log.fatal(“mensagem”);
10. Level
• Uma requisição de log é dita habilitada se seu level for maior
ou igual ao level do seu logger
• Caso contrário, a requisição é dita desabilitada
11. Exemplo
Logger logger = Logger.getLogger(quot;com.fooquot;);
logger.setLevel(Level.INFO);
//Essa requisição é habilitada, porque WARN >= INFO.
logger.warn(quot;Low fuel level.quot;);
//Essa requisição é desabilitada, porque DEBUG < INFO.
logger.debug(quot;Starting search for nearest gas station.quot;);
12. Appenders & Layouts
• Saída para eventos de logging
Interface org.apache.log4j.Appender
• Formatação de eventos de logging
Interface org.apache.lo4j.Layout
13. Appenders Disponíveis
Appender Saída
org.apache.log4j.ConsoleAppender Console (System.out ou
System.err)
org.apache.log4j.FileAppender Arquivo
org.apache.log4j.RollingFileAppender Arquivo (após um certo tamanho,
faz backup do antigo e começa
um novo)
org.apache.log4j.net.SMTPAppender E-mail
org.apache.log4j.nt.NTEventLogAppender NT Event Log
org.apache.log4j.net.SyslogAppender UNIX syslog daemon
org.apache.log4j.net.TelnetAppender Servidor acessível via telnet
14. Layouts Disponíveis
Layout Formato
org.apache.log4j.SimpleLayout “DEBUG – mensagem”
org.apache.log4j.TTCCLayout “176 [thread] INFO categoria –
mensagem”
org.apache.log4j.PatternLayout Depende da string de formatação
org.apache.log4j.HTMLLayout HTML
org.apache.log4j.xml.XMLLayout XML
15. PatternLayout
• As seguintes opções estão disponíveis:
c: Categoria do evento de log
C: Nome da classe que fez a rwuisição de log
d: Data do evento de log. Deve ser seguido de um formater de data
entre chaves. Por exemplo, %d{HH:mm:ss,SSS} ou %d{dd MMM
yyyy HH:mm:ss,SSS}. Se nenhum formater for fornecido, o formato
da ISO8601 será utilizado
F: Nome do arquivo da requisição do evento de log
l: Localização da classe que invocou a requisição que gerou o evento de
log
L: Número da linha da qual a requisição do evento de log foi disparada
n: Separador de linha dependente de plataforma
M: Nome do método no qual o evento de log foi lançado
p: Prioridade do evento de log
t: Nome da thread que gerou o evento de log
m: Mensagem de log
19. PropertyConfigurator
public class MyApp {
static Logger logger = Logger.getLogger(MyApp.class.getName());
public static void main(String[] args) {
// BasicConfigurator substituído por PropertyConfigurator.
PropertyConfigurator.configure(args[0]);
logger.info(quot;Entering application.quot;);
Bar bar = new Bar();
bar.doIt();
logger.info(quot;Exiting application.quot;);
}
}
23. Performance
• Evitando o custo da construção da mensagem:
log.isDebugEnabled();
log.isInfoEnabled();
...
log.isFatalEnabled();
• Quando a requisição está habilitada, duplica o esforço
24. Hierarquia de Loggers
• Membros separados por “.”
• br.ufrj.cos.lens.Processo
Logger br
Logger br.ufrj
Logger br.ufrj.cos
Logger br.ufrj.cos.lens
Logger br.ufrj.cos.lens.Processo
25. Hierarquia de Loggers
• Herança de nível entre loggers
Se um logger não tem um nível explicitamente atribuído, é assumido o
nível explicitamente atribuído ao logger ancestral mais próximo
• Herança de appenders entre loggers
Um evento de logging é emitido para todos os appenders registrados no
logger, e para todos appenders registrados nos loggers ancestrais
26. JUnit
Tópicos
• Tipos de Testes
• O que é JUnit?
• Para que serve?
• Como usar o JUnit?
• JUnit 4
• Exemplo
• Asserções
• Fixtures
• Exceções Esperadas
• Outras Anotações
• Teste Siutações de Falha
• Limitações do JUnit
• Como escrever bons testes?
• Como descobrir testes?
• Testes como documentação
27. Tipos de Testes
• Testes de Unidade
Testam unidades de lógica. Em linguagens orientadas a objetos,
unidades geralmente representam métodos, mas podem também
representar um objeto ou ainda um estado de um método
Ignoram condições ou dependências externas. Testes de unidade usam
dados suficientes para testar apenas a lógica da unidade em questão
• Testes de Integração
Testam como uma coleção de unidades interage entre si ou com o
ambiente onde executam
• Testes Funcionais (caixa-preta)
Testam casos de uso de uma aplicação. Validam a interface do usuário,
operações requisitadas, etc.
28. O que é JUnit?
• Um framework que facilita o desenvolvimento e execução de
testes de unidade em código Java
Uma API para construir os testes: junit.framework.*
Aplicações para executar testes: TestRunner
29. Para que serve?
• “Padrão” para testes de unidade em Java
Desenvolvido por Kent Beck e Erich Gamma
Design muito simples
• Testar é uma boa prática, mas é chato. JUnit torna as coisas
mais agradáveis, facilitando:
A criação e execução automática dos testes
A apresentação dos resultados
• JUnit pode verificar se cada unidade de código funciona da
forma esperada
Permite agrupar e rodar vários testes ao mesmo tempo
Na falha, mostra a causa em cada teste
• Serve de base para extensões
30. Como usar o JUnit?
• Há várias formas de usar o JUnit. Depende da metodologia de
testes que está sendo usada
Código existente: precisa-se escrever testes para classes que já foram
implementadas
Desenvolvimento guiado por testes (TDD): código novo só é escrito se
houver um teste sem funcionar
• Onde obter o JUnit?
www.junit.org
• Como instalar?
Incluir o arquivo junit.jar no classpath para compilar e rodar os
programas de teste
• Extensões do JUnit
Permitem usá-lo para testes funcionais e de integração
31. JUnit 4
• A versão 4 do JUnit acabou de ser lançada (abril de 2006)
• Ela usa as ferramentas disponíveis na versão 5 do Java para
fazer com que desenvolver os testes seja ainda mais fácil
• Vamos apresentar o JUnit 4
• É usado com adaptadores em aplicativos antigos
• Em breve poderemos abandonar os adaptadores
33. Asserções
• Asserções são métodos de junit.framework.Assert
Afirmam que certas condições são verdadeiras
Causam AssertionFailedError se falharem
• Principais asserções
assertEquals(objetoEsperado, objetoRecebido)
assertTrue(valorBooleano)
assertNotNull(objeto)
assertSame(objetoUm, objetoDois)
fail()
34. Fixtures
• São dados reutilizados por vários testes
• Devem conter apenas dados suficientes
• O JUnit 4 provê duas novas anotações para os métodos de set
up e tear down:
@Before: Método anotado com @Before executa antes de todo teste
@After: Método anotado com @After executa depois de cada teste
• Podemos ter quantos @Before e @After quantos forem
necessários
• É possível herdar dos métodos @Before e @After. O JUnit
executa os métodos @Before da superclasse antes dos da
subclasse
36. Fixtures
• One-time set up e tear down
JUnit4 provê as anotações @BeforeClass and @AfterClass para one-
time set up e tear down
Estas anotações rodam o código do set up uma vez antes de todos os
testes e do tear down uma vez depois de todos os testes
38. Exceções Esperadas
• É tão importante testar o cenário de falha do seu código quanto
o de sucesso
• O JUnit 4 facilita o teste quando uma exceção é esperada. A
anotação @Test recebe a exceção que deve ser lançada pelo
método de teste como parâmetro
40. Outras Anotações
• Ignorando um teste
A anotação @Ignore faz com que o teste não seja rodado e seja
relatado que não foi rodado
Pode-se passar uma String como parâmetro para a anotação @Ignore
que explique porque o teste foi ignorado.
• Determinando o tempo limite de um teste
Você pode passar um tempo limite como parâmetro para a anotação test
para especificar um período em limissegundos
Se o teste levar mais que esse tempo, ele falha
41. Teste Situações de Falha
• É tão importante o cenário de falha do seu código quanto o de
sucesso
• Método fail() provoca uma falha
Use para verificar se exceções ocorrem quando se espera que elas
ocorram
@Test public void entityNotFoundException() {
resetEntityTable();
try {
ParameterEntityTag tag = parser.resolveEntity(“bogus”);
fail(“Devia ter causado a exceção EntityNotFoundException!”);
} catch (EntityNotFoundException e) {
}
}
42. Limitações do JUnit
• Acesso aos dados de métodos sob teste
Métodos private e variáveis locais não podem ser testados com JUnit
Dados devem ser pelo menos friendly (package-private)
43. Como escrever bons testes?
• JUnit facilita bastante a criação e execução de testes,
mas elaborar bons testes exige mais
O que testar? Com saber se testes estão completos?
• Teste tudo o que pode falhar
Métodos triviais (get/set) não precisam ser testados
E se houver uma rotina de validação no método set?
• É melhor ter testes a mais que testes a menos
Escreva testes curtos (quebre testes maiores)
Use assertNotNull() (reduz drasticamente erro de NullPointerException
difíceis de encontrar)
Reescreva e altere o design de seu código para que fique mais fácil de
testar: promove design melhor!
44. Como descobrir testes?
• Listas de tarefas (to-do-list)
Comece implementando os testes mais simples e deixe os testes
“realistas” para o final
Requisitos, use-cases, diagramas UML: reescreva s requerimentos em
termos de testes
Quebre requisitos complexos em pedaços menores
• Bugs revelam testes
Achou um bug? Não conserte sem antes escrever um teste que o pegue
(se você não o fizer, ele volta!)
• Descoberta de testes é atividade de análise e design
Sugerem nomes e estrutura de classes da solução
Permitem que se decida sobre detalhes de implementação após a
elaboração do teste
45. Testes como documentação
• Testes são documentação executável
Execute-os periodicamente para mantê-los atualizados
Use nomes significativos
Mantenha-os simples!
• As asserções do JUnit possuem um argumento para descrever o que está
sendo testado
Quando presente é o primeiro argumento
A mensagem passada será mostrada em caso de falha
Use, sempre que possível
assertEquals(“Array deve coincidir!”, esperado, testArray);
assertNotNull(“obj deve ser null!”, obj);
assertTrue(“xyz() deve retornar true!”, a.xyz());
46. Documentação
Tópicos
• Comentários e Documentação
• Tags do JavaDoc
• Tipos de Documentação
• Tags Comuns
• Tags de Classes
• Tags de Variáveis
• Tags de Métodos
47. Comentários e Documentação
• É possível gerar documentação automaticamente em Java pelo
uso de Comentários de Documentação
• O Java possui uma ferramenta para gerar a documentação a
aprtir dos comentários inseridos no código fonte chamada
JavaDoc
• O JavaDoc extrai os comentários /** ... */, especiais de
documentação embutidos no código, gerando um arquivo no
formato html convencional
• O JavaDoc processa apenas comentários de documentação
para membros de classe declaradas como public ou protected
• Comentários em membros do tipo private ou friendly serão
ignorados a menos que se explicite sua inlcusão
48. Comentários e Documentação
• Há duas maneiras de se trabalhar com o JavaDoc:
Embutindo-se código HTML
Usando tags de documentação
• Embutindo HTML
O JavaDoc permite o uso de comandos HTML diretamente nos
comentários de documentação
É permitido o uso de qualquer comando de formatação, tal como <tt> e
<b>, mas não se pode fazer uso de comandos estruturais, tais como
<h2> e <hr>; pois o JavaDoc já insere seus próprios comandos
estruturais
49. Comentários e Documentação
/**
* É possível <b> até </b> gerar uma lista
* <ol>
* <li> item um
* <li> item dois
* <li> item três
* </ol>
*/
• Os asteriscos iniciais das linhas são opcionais e ignorados pelo
JavaDoc
50. Tags do JavaDoc
• Tags são comandos que permitem formatação adicional da
documentação e são sempre iniciados por @:
@author @return
{@code} @see
{@docRoot} @serial
@deprecated @serialData
@exception @serialField
{@inheritDoc} @since
{@link} @throws
{@linkplain} {@value}
{@literal} @version
@param
51. Tipos de Documentação
• Há três tipos principais de documentação: o de classes, o de
variáveis e o de métodos
• Devido a diferenças entre esses tipos, algumas tags são
exclusivas para cada um deles
52. Tags Comuns
• Apenas as seguintes tags são utilizadas para qualquer tipo:
@see
@since
@deprecated
{@link}
{@linkplain}
{@docroot}
53. Tags de Classes
• As tags abaixo podem ser utilizadas para documentação de
classes e interfaces:
@see
@since
@deprecated
@serial
@author
@version
{@link}
{@linkplain}
{@docRoot}
54. Tags de Classes
/**
* A class representing a window on the screen.
* For example:
* <pre>
* Window win = new Window(parent);
* win.show();
* </pre>
*
* @author Sami Shaio
* @version %I%, %G%
* @see java.awt.BaseWindow
* @see java.awt.Button
*/
class Window extends BaseWindow {
...
}
55. Tags de Variáveis
• As tags abaixo podem ser utilizadas para documentação de
variáveis:
@see
@since
@deprecated
@serial
@serialField
{@link}
{@linkplain}
{@docRoot}
{@value}
56. Tags de Variáveis
/**
* The X-coordinate of the component.
*
* @see #getLocation()
*/
int x = 1263732;
57. Tags de Métodos
• As tags abaixo podem ser utilizadas para documentação de
métodos e construtores:
@see
@since
@deprecated
@param
@return – não pode aparecer em construtores
@throws
@exception
@serialData -
{@link}
{@linkplain}
{@inheritDoc}
{@docRoot}
58. Tags de Métodos
/**
* Returns the character at the specified index. An index
* ranges from <code>0</code> to <code>length() - 1</code>.
*
* @param index the index of the desired character.
* @return the desired character.
* @exception StringIndexOutOfRangeException
* if the index is not in the range <code>0</code>
* to <code>length()-1</code>.
* @see java.lang.Character#charValue()
*/
public char charAt(int index) {
...
}
59. Fim
Parabéns!! Chegamos ao fim da
apresentação de Frameworks e
Documentação!!
Agora sabemos criar aplicações que
utilizam esses frameworks para torná-
las mais robustas!
Próximos passos:
Padrões de Projeto!