Aurock

1, 2, 3, testando…

Testar é um passo obvio na escrita de código. Sempre que terminamos de escrever (ou enquanto ainda estamos escrevemos), executamos o código para verificar se o resultado esperado está sendo alcançado. Afinal, um código que não executa ou não gera o resultado, não serve pra nada.

Acredito que a maioria, começa simplesmente executando o código (abrindo a página no browser, compilando e executando pela IDE ou símplesmente fazendo uma chamada via cli) e verificando manualmente o resultado. Quando o resultado não corresponde, adicionamos mais informação, via log, ferramentas de debug ou uma exibição de informações própria da linguagem (como var_dump em PHP) e procuramos o problema, ou onde o que deveria ter sido feito não aconteceu.

Como todo bom preguiçoso, clicar em uma pagina ou IDE começa a ficar chato depois de um tempo, principalmente quando se necessita de interação para chegar onde se quer testar. O que acontece quando seu software cresce? Quando seu código não é mais um script de 300 linhas e sim um emaranhado de classes e chamadas entre elas?

Testando código com código

Para facilitar os testes durante a escrita de código, podemos utilizar código para testar código, ou seja, executamos o nosso código, capturamos o resultado e validamos, utilizando tambem código. Um exemplo bastante simples em PHP:

<?php

function soma($num1, $num2) {
    return $num1 + $num2;
}

$resultado = soma(1, 1);
if ($resultado != 2) {
    die("Resultado da soma errado");
}

Por que fazemos isso? Alguns dos meus motivos são:

  • É mais facil retestar após algumas alterações no código;
  • É mais facil testar quando o resultado não é algo trivial como um inteiro ou booleano;

Conforme o código cresce, uma opção é separar os testes, e testar partes menores por vez, e não somente o todo de uma unica vez.

Testes unitários

Um dos tipos de teste é o teste unitário, ou seja, um teste de unidade. Podemos definir uma unidade como o menor pedaço de código que podemos testar. A unidade mais utilizada para OOP são metodos de classe.

A idéia é uma checar pedaços pequenos de código, o que pode facilitar o debug, acelerar a execução do seu teste (quando a execução do código completo é relativamente lenta e você precisa testar apenas uma chamada, por exemplo) e isolar o código, evitando que um erro inserido em um determinado código seja interpretado como um erro em outro lugar (se a função X está retornando um valor incorreto mas tudo o que você percebe é um comportamento inesperado na função Z).

Outro benefício é que podemos aumentar as opções de teste, exercitando nosso código de diversas outras maneiras, e não só mais o “caminho feliz”. Podemos verificar se nosso código realmente filtra as entradas, valida os valores e executa o comportamento condicional correto. O que é um benefício, também pode ser tornar um malefício quando o nosso código só falha quando não isolado, ou seja, quando chamado em conjunto com outro pedaço de código. Ai entram os testes de integração.

Testes de integração

Testes de integração são exatamente o oposto de testes unitários. O objetivo é garantir que o resultado é atingido quando todo ou parte do código interage, e é utilizado em conjunto. Porém, os limites não são necessáriamente definidos. Podemos testar a integração entre duas funções, quatro metódos, seis classes, ou mais de um recurso (banco de dados, API, etc.).

Qual é melhor?

Aquele que é feito. Ambos tem seu valor e são aplicados por razões diferentes mas um não substitui o outro. Os testes unitários geram grande confiabilidade no código escrito, porém, não tem como garantir o mesmo resultado quando outra parte do código muda. Principalmente quando essa outra parte não está sob o controle do desenvolvedor. Os códigos de integração podem verificar essa interação, porém, podem se tornar muito lentos em diversos casos.

Outros tipos de teste

Os testes unitários e de integração não são os únicos tipos de teste disponiveis. Existem diversos outros, lembrando que os testes que escrevemos, muito provavelmente, acabam sendo de mais de um tipo por vez. Alguns tipos são:

  • End-to-end: Sãos os tipos de teste em que é feita a verificação do processo como um todo, normalmente simulando um usuário;
  • White-box: Testes onde o código de teste conhece a implementação do código sendo testado. Um exemplo é quando estamos testando se um determinado código interage com o banco de dados, então verificamos se a chamada para o banco de dados foi feita;
  • Black-box: Testes onde o código não conhece a implementação. Utilizando o mesmo exemplo, verificamos se a interação com o banco de dados foi feita, verificando o próprio banco de dados. No caso de um insert, procurariamos pelo registro inserido;
  • Smoke test: Testes rápidos, e muitas vezes rasos. O objetivo é apenas garantir um mínimo de confiança. Normalmente testamos apenas o “caminho feliz”, ou seja, apenas as partes mais importantes;
  • Regreção: São testes que garantem que os demais códigos ainda funcionam após as alterações. Ou seja, servem para garantir compatibilidade dentro do código;
  • Aceitação: Até aqui, os testes garantem que o código funciona. Esse é o teste que garante que o código faz o que deveria fazer, ou seja, atende os requisitos do projeto;
  • Automatizados: São testes que podem ser executados de forma automatizada, sem necessidade de interação. Muito utilizados em processos de integração contínua (IC).

Não sou profissional se não testo?

Os testes existem por um objetivo principal: atestar qualidade. Quando escrevemos testes, queremos garantir que nosso código funciona. Podemos verificar se nosso código é robusto e está preparado para quando a situação não é ideal (parâmetros errados, falha de conexão, etc.). Os testes, hoje, talvez sejam a maneira mais facil e comum de se atestar qualidade. A não ser que você tenha outra maneira de fazer isso, escrever testes é um bom sinal de profissionalismo (mas não o garante).

TDD?

Desenvolvimento guiado por testes (Test-driven development, ou TDD), é um processo de se escrever testes antes do próprio codigo ser escrito, o que, supostamente, força o desenvolvedor a refletir sobre o código e por resultado, escreve um código de melhor qualidade. O real benefício do TDD é bastante discutivel, principalmente pelo fato de qualidade ser um atributo bastante subjetivo. Porém, é uma discussão que não cabe nesse post.

Um ponto importante é que, principalmente conforme nossa experiencia aumenta, não necessáriamente precisamos escrever esse teste antes para obter os beneficios. Muitas vezes, antes de começar, já temos uma ideia do que código que queremos escrever e conseguimos guiá-lo a uma melhor qualidade. O que acaba por ser um processo de escrever os testes simultaneamente, nem antes, nem depois.

Compartilhe nas Redes Sociais

Share on facebook
Facebook
Share on twitter
Twitter
Share on whatsapp
WhatsApp
Share on telegram
Telegram

OUTROS POSTS

Damos valor à sua privacidade

Nós e os nossos parceiros armazenamos ou acedemos a informações dos dispositivos, tais como cookies, e processamos dados pessoais, tais como identificadores exclusivos e informações padrão enviadas pelos dispositivos, para as finalidades descritas abaixo. Poderá clicar para consentir o processamento por nossa parte e pela parte dos nossos parceiros para tais finalidades. Em alternativa, poderá clicar para recusar o consentimento, ou aceder a informações mais pormenorizadas e alterar as suas preferências antes de dar consentimento. As suas preferências serão aplicadas apenas a este website.

Cookies estritamente necessários

Estes cookies são necessários para que o website funcione e não podem ser desligados nos nossos sistemas. Normalmente, eles só são configurados em resposta a ações levadas a cabo por si e que correspondem a uma solicitação de serviços, tais como definir as suas preferências de privacidade, iniciar sessão ou preencher formulários. Pode configurar o seu navegador para bloquear ou alertá-lo(a) sobre esses cookies, mas algumas partes do website não funcionarão. Estes cookies não armazenam qualquer informação pessoal identificável.

Cookies de desempenho

Estes cookies permitem-nos contar visitas e fontes de tráfego, para que possamos medir e melhorar o desempenho do nosso website. Eles ajudam-nos a saber quais são as páginas mais e menos populares e a ver como os visitantes se movimentam pelo website. Todas as informações recolhidas por estes cookies são agregadas e, por conseguinte, anónimas. Se não permitir estes cookies, não saberemos quando visitou o nosso site.

Cookies de funcionalidade

Estes cookies permitem que o site forneça uma funcionalidade e personalização melhoradas. Podem ser estabelecidos por nós ou por fornecedores externos cujos serviços adicionámos às nossas páginas. Se não permitir estes cookies algumas destas funcionalidades, ou mesmo todas, podem não atuar corretamente.

Cookies de publicidade

Estes cookies podem ser estabelecidos através do nosso site pelos nossos parceiros de publicidade. Podem ser usados por essas empresas para construir um perfil sobre os seus interesses e mostrar-lhe anúncios relevantes em outros websites. Eles não armazenam diretamente informações pessoais, mas são baseados na identificação exclusiva do seu navegador e dispositivo de internet. Se não permitir estes cookies, terá menos publicidade direcionada.

Visite as nossas páginas de Políticas de privacidade e Termos e condições.

Nós armazenamos dados temporariamente para melhorar a sua experiência de navegação e recomendar conteúdo de seu interesse. Ao utilizar nossos serviços, você concorda com tal monitoramento.