Criando testes de Log com Laravel

Victor Gustavo da Silva Oliveira
sysvale
Published in
4 min readJul 23, 2019
Photo by Ken Archer on Thunder

Em algumas situações, enquanto desenvolvedores, precisamos enviar alguns avisos, sejam eles interrompendo a execução do programa, ou simplesmente evidenciando algum erro ou acontecimento que pode gerar um erro. A estes avisos, costumamos dar o nome de logs. A utilização dos logs é uma mão na roda para que estas mensagens sejam geradas de forma eficiente, sempre que desejarmos e da forma que precisarmos.

Mas, como garantir que estas mensagens realmente estão sendo enviadas, ou ainda, se estão sendo enviadas da forma que queremos? Para isto, podemos testar essa funcionalidade, antes de disponibilizá-la para o nosso produto final.

A realização de testes para o desenvolvimento do seu código é uma tarefa muito importante, embora muitos decidam por não utilizá-los. Testes são um guia para o bom funcionamento do sistema e garantem estabilidade e confiabilidade no código desenvolvido.

O framework Laravel não oferece, em sua documentação, uma descrição ou algum teste dos logs explicitamente. No entanto, alguns pacotes disponibilizados por terceiros fazem isso de forma eficiente. Neste post, vamos tratar do Log Fake, de Tim MacDonald (https://github.com/timacdonald/log-fake), que foi criado para auxiliar no desenvolvimento eficiente e simples de testes de logs, tornando esta tarefa bastante interessante.

Este tutorial supõe que existe um projeto Laravel versão 5.7 já configurado e alguns conhecimentos mínimos de PHP.

Como testar?

O primeiro passo então é adicionar e instalar o pacote, utilizando o composer:

$ composer require timacdonald/log-fake --dev

Depois de instalado, sempre que precisar nos testes, devem ser importados dois módulos: LogFake e Facades\Log, como no exemplo a seguir:

<?phpuse TiMacDonald\Log\LogFake;
use Illuminate\Support\Facades\Log;
//...

A partir daí, podemos começar nossos testes.

Teste básico

Crie o teste através do artisan:

php artisan make:test LogTest

A seguir, copie e cole o seguinte código no novo teste (pode excluir tudo o que o Laravel criou para você automaticamente):

<?phpnamespace Tests\Feature;use Tests\TestCase;
use TiMacDonald\Log\LogFake;
use Illuminate\Support\Facades\Log;
class LogTest extends TestCase
{
public function testLog()
{
Log::swap(new LogFake);
Log::info('Donuts have arrived');
//Com asserção sem função de callback
Log::assertLogged('info');
//Com função de callback
Log::assertLogged('info', function ($message, $context) {
return str_contains($message, 'Donuts');
});
}
}

Agora, podemos rodar o nosso teste. Como o Laravel está instalado, basta executar o comando:

$ vendor/bin/phpunit --filter LogTest

O que este teste faz? Inicialmente, trocamos a instância dos logs para que sejam recebidos pelo LogFake em Log::swap(new LogFake). A seguir, criamos um log para o teste, com a mensagem “Donuts have arrived” e fazemos dois testes. O primeiro, se o log que foi enviado é do tipo info. Depois testamos se na mensagem que foi logada, aparece em algum momento a palavra “Donuts” através de uma função de callback. Simples assim :)

Existem ainda outros tipos de testes de log que este módulo pode testar, como por exemplo se os seus logs são feitos através de um canal (slack, por exemplo), e você estiver declarando explicitamente este canal, pode ser feito o teste da seguinte forma:

//teste
...
Log::channel('slack')->alert('It is 5pm, go home');//O log foi enviado pelo canal do slack
Log::channel('slack')->assertLogged('alert'); // ✅
//Se o teste for efetuado da forma anterior...
Log::assertLogged('alert'); // ❌

Da mesma forma, é possível testar pilhas de mensagens, basta trocar a chamada de channel para stack([lista_de_itens]), em todos os passos.

Finalmente, temos os tipos de asserção que podem ser feitas. São elas:

  • assertLogged($level, $callback = null): Testa se o log enviado tem o nível indicado (warning, error, etc), e pode-se criar uma função de callback para testar o conteúdo;
  • assertLoggedMessage($level, $message): Testa se o log enviado tem o nível e exatamente a mesma mensagem indicados;
  • assertLoggedTimes($level, $times = 1, $callback = null): Testa se a quantidade de vezes que foram enviados logs nos níveis indicados corresponde ao valor de $times. Pode ter uma função de callback para testar o conteúdo;
  • assertNotLogged($level, $callback = null): Testa se nenhum log do nível indicado foi enviado. Pode ter função de callback para testar o conteúdo;
  • assertNothingLogged(): Testa se não foi emitido nenhum tipo de log.

Conclusão

Testar seu código é uma ferramenta interessante para assegurar que o seu trabalho está certo, e evita que surjam demandas futuras (não entenda mal, elas sempre existirão, mas diminuir a quantidade de trabalho é sempre uma boa ideia). A documentação do Laravel é muito extensa e cobre quase todos os casos que temos para testes, no entanto existem situações que não conseguimos, utilizando a mesma, fazer o que queremos. Este artigo é um pequeno guia para facilitar a criação de um teste que não é tão trivial, mas que pode ser necessário no futuro. Divirta-se.

Fontes

--

--