Capítulo 1. Automatizando Testes

Mesmo bons programadores cometem erros. A diferença entre um bom programador e um mau programador é que o bom programador usa testes para detectar seus erros o mais cedo possível. Quanto antes você testar por um erro, maiores são suas chances de encontrá-lo e consertá-lo. Isso explica porque deixar os testes para um momento logo antes do lançamento do programa é tão problemático. A maioria dos erros nem sequer chega a ser encontrado, e o custo de consertar aqueles que você encontra é tão alto que você tem que fazer uma triagem com os erros porque você simplesmente não consegue consertar todos.

Testar com o PHPUnit não é uma atividade totalmente diferente do que você já costuma fazer. É apenas uma forma diferente de fazê-lo. A diferença está entre testar, isto é, verificar que seu programa se comporta como o esperado, e fazer uma bateria de testes, fragmentos de código executáveis que automaticamente testam se as partes (unidades) do programa estão corretas. Esses fragmentos de código executáveis são chamados de testes unitários.

Neste capítulo vamos de um simples código de teste baseado em printaté um teste totalmente automatizado. Imagine que nos peçam para testar um vetorembutido do PHP. Uma pequena funcionalidade a se testar é a função count(). Para um vetor criado recentemente esperamos que a função count() retorne 0. Após adicionarmos um elemento, count() deverá retornar 1. Exemplo 1.1 mostra o que queremos testar.

Exemplo 1.1: Testando operações de vetores

<?php
$componente = array();
// espera-se que $componente esteja vazio.

$componente[] = 'elemento';
// espera-se que $componente contenha um elemento.
?>


Um jeito bem simples de verificar se estamos obtendo os resultados que esperamos é imprimir o resultado de count() antes e depois de adicionar o elemento (veja Exemplo 1.2). Se obtivermos 0 e depois 1, array e count() se comportaram como esperado.

Exemplo 1.2: Usando print para testar operações de um vetor

<?php
$componente = array();
print count($componente) . "\n";

$componente[] = 'elemento';
print count($componente) . "\n";
?>
0
1


Agora gostaríamos de mudar de testes que exigem interpretação manual para testes que podem executar automaticamente. Em Exemplo 1.3, escrevemos a comparação do valor esperado e do real em nosso código de teste e imprimimos ok se os valores forem iguais. Se alguma vez virmos uma mensagem não ok saberemos que algo está errado.

Exemplo 1.3: Comparando os valores esperado e real para testar operações de vetores

<?php
$componente = array();
print count($componente) == 0 ? "ok\n" : "não ok\n";

$componente[] = 'elemento';
print count($componente) == 1 ? "ok\n" : "não ok\n";
?>
ok
ok


Agora fatoramos a saída de comparação dos valores esperado e real em uma função que gera uma Exceção (Exception) onde há uma discrepância (Exemplo 1.4). Isso nos traz dois benefícios: a escrita dos testes se torna mais fácil e só obteremos saída quando algo estiver errado.

Exemplo 1.4: Usando uma função de asserção para testar operações de vetores

<?php
ini_set('error_log', '');
ini_set('display_errors', 'Off');

$componente = array();
assertTrue(count($componente) == 0);

$componente[] = 'elemento';
assertTrue(count($componente) == 1);

function assertTrue($condicao)
{
if (!$condicao) {
throw new Exception('Asserção falhou.');
}
}
?>


O teste agora está totalmente automatizado. Em vez de apenas testar como fizemos em nossa primeira versão, com esta versão temos um teste automatizado.

O objetivo de usar testes automatizados é cometer menos erros. Ainda que seu código não fique perfeito, mesmo com testes excelentes, você perceberá uma redução dramática nos defeitos assim que começar a automatizar os testes. Testes automatizados darão a você uma justificada confiança em seu código. Você poderá usar essa confiança para atravessar barreiras mais difíceis de design (Refatoração), melhorar as relações com sua equipe (Testes Inter-Equipes) e clientes, além de voltar para casa toda noite com a prova de que seu sistema está melhor agora do que estava de manhã, graças aos seus esforços.

Please open a ticket on GitHub to suggest improvements to this page. Thanks!