Separação de Conceitos
Testes manuaisTestes de UnidadeTestes de IntegraçãoTestes de AceitaçãoTestes de CargaTestes de Stress
Anatomia de Teste (jUnit)
Um teste deve testar apenas uma pequena funcionalidadeDeve ser claro o que o teste deve fazer
Exemplo:
Teste conciso?Diz claramente o que está sendo testado?
public class RotinaBackupTest {public void setup() {....}public void tearDown() {.....}@Testpublic void testBackup() {
...}
}
Exemplo:
Diz claramente o que está sendo testado AGORA?
public class RotinaBackupTest {@Testpublic void deveriaCriarArquivoTemporarioAoRealizarBackup() {
...}@Testpublic void deveriaCompactarArquivoAoFinalizarBackup() {
...}
}
Nomes são importantes
Lembre-se quando você bater o olho no método do teste, você deve saber exatamente o que está sendo testado.
Testes de integração
Testam a interação entre componentes do sistemaUsado geralmente nas fronteiras do sistema:Banco de dadosAcesso a LdapLeitura de arquivosetc...
Testes de integração
Devem ser isolados também, pois o comportamento deve ser repetitível.São mais difíceis de ser escritos.bibliotecas que ajudam:DBUnit - permite mockar banco de dadosUnboundid - instancia um servidor de ldapJetty - pemite subir um container de servletEtc...
Outros tipos de testes
Testes de aceitação - testes desenvolvidos para que o usuário final possa averiguar se o sistema está tendo o comportamento esperado, devido a fragilidade destes testes, são raramente implementados.Ferramentas:Selenium, Phantomjs, Capybara, etc...
Outros tipos de testes
Testes de carga: testes que tem como premissa gerar um carga no sistema simulando o seu comportamento quando diversos usuários estão usando o programa.Ferramentas:JMetter, apache AB, Selenium Grid, etc...
Outros tipos de testes
Testes de Stress: testes que tem como premissa gerar um stresse no sistema para ver como ele se comporta. Será que vai perder dados? Será que o número do pool está bem escalonado?Ferramentas:JMetter, apache AB, etc...
Piramide de testes
99% do código deve ser testado
60% deve ser testado
10% deve ser testado
Cobertura do teste
Problemas comuns nos testes
Os testes de unidade devem ser isolados:● somente uma classe deve ser testada● Dependências devem ser mockadas
Mockito
Biblioteca usada para fazer mocks de classesPermite definir o comportamento das dependenciasSimples de usar
Exemplo: public class CadastroDeUsuarioActionTest {
@Mock
private GerenciadorUsuarios gerenciadorUsuarios;
@Mock
private MensagensTela mensagensTela;
private CadastroUsuarioAction cadastroUsuario;
@Before
public void setup(){
// use static imports para classes mockito
initMocks(this);
cadastroUsuario = new CadastroUsuarioAction();
cadastroUsuario.gerenciadorUsuarios = gerenciadorUsuarios;
cadastroUsuario.mensagensTela = mensagensTela;
}
Exemplo: Continuação@Test
public void deveriaEmitirAlertaParaUsuarioParaErrosDeCadastramentoNoGerenciadorUsuarios(){
Usuario usuario = new Usuario();
doThrow(new CadastroInconsistenteException()).when(gerenciadorUsuarios).salvar(usuario);
cadastroUsuario.salvar(usuario);
verify(mensagensTela).adicionarMensagemErro("Cadastro inconsistente");
}
}
DSL para gravação comportamentodoReturn(usuario).when(cadastroUsuario).salvar(usuario);doCallRealMethod().when(cadastroUsuario).salvar(usuario);doAnswer(answer).when(cadastroUsuario).salvar(usuario);doThrow(toBeThrown).when(cadastroUsuario).salvar(usuario);
reset(cadastroUsuario);
HamCrest
Biblioteca para gerar asserçõesMelhor que asserts do junitpossui dsl para tratamento de asserções
Exemplo: HamcrestassertThat(usuario, is(notNullValue()));// coleçõesassertThat(usuario, isIn(usuarios));assertThat(usuarios, hasItems(helena,joana));
// reflectionsassertThat(usuario, hasProperty("nome"));assertThat(usuario, hasProperty("nome",is("carlos")));
assertThat(nomeUsuario, not(is("carlos")));
assertThat(saldoConta, is(positivo)); // milagre
Finalmente:
Dicas finais:Jcobertura - dedo duro do codigo não testadoSonarQube já tem jcobertura por padrão para os projetos analisados.Use TDD (tente pelo menos), o efeito colateral é que já terá um teste implementado para cada implementação de código que fizer.