Fundamentos de Teste Automatizados

Por mais que se planeje a construção de um software,fazendo o uso de tecnologias de ponta do mercado, adotando as melhores práticas no desenvolvimento de uma aplicação, erros são passíveis de ocorrer, o que acaba gerando grandes dores de cabeça para usuários projetistas e prejuízos astronômicos para empresas principalmente se for uma aplicação com alta criticidade.
Quem já passou por isso sabe o quão desagradável é ficar na mão quando um programa fecha de forma inesperada devido a um bug no sistema, este fato poderia ter sido evitado caso a equipe em questão estivesse como hábito a utilização das ferramentas de teste apropriadas para a detecção do bug.
Portanto um dos benefícios quando temos o hábito de testar um software é detectar de forma rápida se determinada mudança acaba violando determinada regra e qual impacto que essa mudança pode trazer para quem está utilizando o software, simulando casos reais e avaliando se todas as funcionalidades entregues estão funcionando de forma correta e segura, em outras palavras é no teste que podemos avaliar se o programa está funcionando de forma esperada. Justamente por todos esses argumentos já citados que equipes e empresas gastam tempo e recursos na adoção de ferramentas e metodologias de teste.
Atualmente existem diversos tipos de testes para detectarmos os mais variados cenários(daria até para fazer um livro) mas o enfoque do artigo será nos testes automatizados.

O que é um teste automatizado?

No decorrer do desenvolvimento e na manutenção de um sistema a complexidade tende a aumentar, projetista e desenvolvedores passam a ter dificuldades em avaliar se os recursos estão funcionais ou não pois o software que antes contemplava poucos cenários agora passa a atender um número muito maior de casos deixando sua complexidade "N" vezes maior..
Para auxiliar os times de alta performance na avaliação de softwares é que utilizamos os testes automatizados que nada mais é que um software escrito por alguém que tem intuito de avaliar o seu sistema.

3 tipos de testes automatizados

Os testes funcionais podem ser feitos de diversas maneiras, mas as 3 abordagens que o mercado mais utiliza que tem como intuito detectar bugs no menor tempo possível sem comprometer a qualidade do sistema são:

1.Teste Unitário
É o teste feito pelo desenvolvedor tem como intuito validar o comportamento funcional do código, em outras palavras estamos testando os métodos de uma classe, com base numa determinada entrada qual resposta que esperamos que aconteça.
Nesse tipo de teste não podemos acessar outros componentes(isto é não podemos criar objetos de outras classes), ou recursos externos(como bd,rede, web services e etc).
Caso haja necessidade de instanciar objetos de outras classes ou simularmos o retorno de algum webservice para executarmos um teste unitário por exemplo utilizamos de um artifício que é mocar um objeto ou serviço(isto é criar um objeto fake ) para podermos simular o resultado esperado. Utilizamos uma ferramenta muito popular usada para realizarmos o mock é o mockito.
Nos testes unitários também utilizamos uma ferramenta muito famosa chamada Junit.

2.Integração
Também conhecido como teste de web service/API é o teste voltado em verificar a comunicação entre componentes/módulos e recursos externos de uma aplicação. O objetivo deste teste é verificar se a interação entre os componentes e APIs está ocorrendo de forma correta.
Geralmente neste tipo de teste utilizamos ferramentas já conhecida por desenvolvedores como SoapUI e PostMan.

3.Funcional
É o teste do ponto de vista do usuário final que tem como finalidade verificar se uma determinada funcionalidade tá sendo executada da forma esperadacomo foi planejada, em outras palavras estamos testando os nossos casos de uso.

Benefícios em Utilizar Teste Automatizados

  • Como já dito acima um dos benefícios em utilizar testes automatizados em um projeto é detectar de forma mais rápida se determinadas mudanças violam regras de negócio.
  • Além disso o uso testes automatizados é uma forma de documentar aplicação, já que quando estamos implementando os testes na nossa aplicação a lógica tende a ser a mais simples clara e objetiva possível,o comportamento dos métodos quais entrada/saídas e os resultados esperados.
  • Redução de custos de manutenção, pois num desenvolvimento de software a etapa de validação,homologação e até mesmo de manutenção é muito custosa, portanto se a sua aplicação estiver com uma boa cobertura de testes certamente você passará por essa etapa sem muitas dores no bolso.

  • Melhorias no design da solução, pois a cada feature nova a aplicação é testada, possibilitando mudanças na estrutura arquitetural de uma aplicação.

TDD - Test Driven Development

Antes de mais nada é importante esclarecermos que TDD é nada mais que um método de desenvolver testes isso significa dizer que o TDD é uma definição da maneira como a equipe irá trabalhar na elaboração dos testes, não é o foco do TDD avaliar se os testes estão sendo bem ou mal executados ou se o projeto tem ou não tem testes.Além disso não significa necessariamente que um software só por ter testes automatizados possa ser de cara já encaixado no padrão do TDD.

Principais Vantagens Na Utilização do TDD

  • Foco nos requisitos isto é no TDD você começa primeiro pelos testes antes de sair de cara implementando algo. Neste momento você não está preocupado como o método será implementado e sim qual o comportamento e esperado dele após inserirmos uma determinada informação.

  • Melhora o design da aplicação pois o código desenvolvido passa a ser testado repetidas vezes, evitando que tenhamos que escrever códigos demasiadamente complexos.

  • Dá mais segurança ao desenvolvedor na hora de implementar novas
    funcionalidades, tendo assim mesmo chance de quebrar a aplicação devido alguma feature nova.

Processo Básico

Bem já que falamos que o TDD é um metodologia para o desenvolvimento de testes abaixo vamos listar alguns itens básicos levados em consideração no TDD.

  • Como já dito acima o TDD prega a cultura de escrever primeiro os testes antes de sair desenvolvendo um método, nesta etapa a preocupação é descrever o comportamento do método baseado numa entrada(é natural que nesta etapa o seu teste ainda esteja falhando pois o componente ainda não foi implementado).
  • Agora sim nessa etapa você deverá implementar o código, os casos de uso e os componentes necessários para que o teste passe.
  • Essa etapa é opcional e avalia a necessidade de refatoração do código mediante a necessidade.

Boas Praticas e Padrão Quando Estamos Implementando Testes Automatizados

Neste tópico vou procurar mostrar algumas das melhores praticas e padrões quando estamos desenvolvendo testes automatizados(eu sei que é um tema polêmico e não existe uma regra universal e cada equipe faz da forma que deseja), mais abaixo procuro demonstrar o que na visão de vários especialistas é importante:

Nomenclatura de Teste (AÇÃO should EFEITO when CENÁRIO)

Dado uma ação qual será o efeito(should efeito) dela mediante aquele cenário(when cenário) exemplos:

Ação : Método Delete
Efeito: Dado um determinado ID deverá excluir um determinado registro do BD.
Cenário: Quando o ID existir

Ação : Método Delete
Efeito: Lançar uma exceção quando a aplicação não encontrar um ID Cenário: Quando o ID não existir

Padrão AAA

  • Arrange : Primeiro instancie os objetos necessários(de new nos objetos que você irá utilizar)
  • Act: execute as ações necessárias isto é faça o que tem de ser feito no método isto é caso seja necessário inserir/atualizar um dado no Banco de Dados por exemplo
  • Assert: declare o que deveria acontecer (resultado esperado).

Princípio da Inversão de Controle(SOLID)

Uma classe A jamais poderá depender da instância de uma classe B(se isso estiver sendo feito esse teste não pode ser chamado de teste unitário). Caso você precise acessar instâncias de outras classes precisaremos criar mocks(objetos fakes como já dito acima).
Isso acaba ajudando na testabilidade do método garantindo assim o isolamento da unidade a ser testada.

Independência

Um teste não pode depender de outro teste e a ordem de como o teste será executado pouco importa, portanto é uma boa pratica que os testes sejam independentes um não pode ficar dependendo de dados do outro.

Cenário Único

Cada teste deve ter um cenário especifico, e sua lógica deve ser a mais simples possível sem o uso de loops ou operadores condicionais.
Se você reparou no exemplo acima foi criado um cenário onde um ID existia e um outro cenário onde não existia o ID.

Previsibilidade

O resultado de um teste deve ser sempre o mesmo para os mesmos dados,evite que o seu teste faça depender de coisas que variam como: timeStamp atual(new Date,instant.now) e valores aleatórios (como random).

24