Capa de post contendo o logo oficial do PestPHP e um exemplo de teste

Introdução ao PestPHP


novidades pest

Conheça o framework de testes que melhora (e muito!) a experiência no desenvolvimento de suítes de testes unitários e funcionais em aplicações PHP.

Um conceito que vem tomando bastante força nos últimos tempos é o developer experience. Assim como os termos UX (user experience), CX (consumer experience) se preocupam com usuário e consumidor respectivamente, o DX é um conceito que se preocupa com a experiência da pessoa desenvolvedora no desenvolvimento de software: Incrementos visuais em IDEs, ferramentas GUI, melhores outputs em aplicações de linha de comando e por aí vai.

Tendo este novo conceito em mente nasce o PestPHP!

Sua proposta como o próprio site oficial diz é ser simples, único e elegante e posso garantir que estes três pilares foram construídos com maestria!

Com o PestPHP conseguimos “enxugar” um caso de teste que precisaria de umas boas 10-20 linhas de código para algo como 4 ou 5.

Print de comparação entre a quantia de linhas necessárias para um teste simples com PHPUnit e com PestPHP

Massa, não é mesmo? Bom, então vamos descobrir como podemos começar agora mesmo a utilizar o Pest como framework de testes em aplicações PHP.

Instalação

O PestPHP pode ser instalado e utilizado em qualquer projeto PHP mas como estamos aqui para falar de Laravel e tópicos relacionados, vamos seguir o exemplo de instalação para aplicações Laravel encontrado na documentação oficial .

TR;DL

No passo de instalação trago praticamente uma tradução da documentação oficial então se inglês não é um problema e você prefira seguir a documentação: pule este passo =)

Pré requisitos

Alguns requisitos precisam ser atendidos para que o Pest possa ser instalado corretamente, são eles:

  • PHP versão >= 7.3
  • Ter um arquivo chamado phpunit.xml na raiz do projeto
  • Ter o PHPUnit na versão ^9.3.10
  • Caso esteja utilizando o Pest com o Laravel (que é nosso caso), ter a dependência Collision na versão ^5.0
  • Garantir que o arquivo composer.json contenha as diretivas ”minimum-stability”: “dev” e "prefer-stable": true

Especificamente para este exemplo será utilizada a instalação do Pest em uma aplicação Laravel, logo, para seguir os próximos passos é necessário ter uma uma aplicação com o Laravel instalado para então adicionar o Pest.

Instalação e configuração

Com todos os requisitos atendidos, vamos instalar o Pest via composer:

composer require pestphp/pest --dev

Para aplicações Laravel existe um plugin chamado pest-plugin-laravel que torna nossa vida ainda mais fácil, uma vez que o Pest já tenha sido instalado vamos instalar também o plugin para Laravel rodando o seguinte comando:

composer require pestphp/pest-plugin-laravel --dev

Com tudo instalado, como não poderia ser diferente, há mais uma facilidade para a configuração do Pest: um comando artisan que preparará o restante da instalação para nós! Basta rodar o comando php artisan pest:install.

A partir deste ponto estamos com tudo pronto para rodar nossos testes!

Em aplicações Laravel, por padrão, temos dois arquivos de testes pré definidos, um de teste unitário e outro de teste “funcional”, vamos utilizá-los para este primeiro exemplo.

Na raiz do projeto vamos executar o Pest através da linha de comando:

./vendor/bin/pest

Ouput dos testes de exemplo utilizando o PestPHP

O Pest se encarregará de encontrar as classes de testes localizadas em tests/ e executá-las, o mais legal é que estas classes apesar de estarem escritas (por padrão) utilizando o PHPUnit como base, o Pest consegue rodar normalmente, este comportamento é bastante interessante pois podemos utilizar uma suíte de testes já existente e ir migrando para o Pest aos poucos.

Iniciando com PestPHP

Caso queira seguir o código utilizado nestes exemplos e nos próximos posts da série sobre o Pest estou utilizando este repositório no Github e cada post relacionado ao Pest terá o código separado por branch, como este é o "esqueleto" da série, estará tudo na master mesmo =)

O plugin do PestPHP para o Laravel já deixou tudo “no esquema” pra gente, agora só precisamos nos preocupar em testar nossas regras e esquecer configurações complexas!

Os padrões de pastas e nomes de arquivos do Pest seguem bem parecidos com o PHPUnit e a estrutura que já existia anteriormente no Laravel. Para criamos nossos próprios testes basta adicionar arquivos nos namespaces Tests\Feature em caso de testes “funcionais” ou Tests\Unit em casos de testes unitários mas vale lembrar que este comportamento pode ser alterado de acordo com as diretivas do arquivo phpunit.xml da raiz do projeto.

Por convenção o Pest utiliza o mesmo padrão do PHPUnit para nomenclaturas de classes de testes, ou seja, temos o nome da classe e a utilização do sufixo Test.php, a diferença é que “por dentro” os arquivos de teste do Pest não são classes e vamos ver mais sobre isso já já.

Dentro da pasta tests/Unit vamos criar um arquivo chamado FirstTest.php e começar a explorar o PestPHP.

Escrevendo o primeiro caso de teste

O intuito deste post é bem introdutório e faremos asserções bem simples muito mais para mostrar a sintaxe e elegância do Pest do que de fato criar casos de teste complexos. Para receber uma notificação quando houver novas postagens sobre o PestPHP e casos de teste mais complexos, assine o feed RSS em seu agregador favorito!

Para indicar que um teste deverá ser executado, ao utilizar o PHPUnit seria necessário criar um método com prefixo test ou utilizar a annotation @test decorando o método de nossa escolha.

Com o Pest podemos utilizar it() ou test() para definir a execução de um teste. Ambas as nomenclaturas são válidas e compartilham do mesmo comportamento, desta forma podemos utilizar a que melhor atender nossas convenções.

Vamos escrever nosso primeiro teste e explorar um pouco mais a sintaxe.

// tests/Unit/FirstTest.php

test('true is true', function() {
    $this->assertTrue(true);
});

A função test() indica que um caso de teste será rodado, esta função pode receber 2 parâmetros:

1- Um nome para o caso de teste. Este nome é, idealmente, descritivo e sucinto, assim como eram as sugestões de nomes para os métodos no PHPUnit. No nosso exemplo utilizei true is true (verdadeiro é verdadeiro) que em conjunto com a diretiva test() mostra claramente o que será testado dentro do bloco todo: testa se verdadeiro é verdadeiro;

2- Um callback contendo as asserções a serem performadas

Note que dentro do callback foi utilizado o $this, mas a que diabos este $this se refere?

No Pest a variável $this está ligada a classe TestCase que foi configurada previamente e neste caso, como utilizamos as configurações padrão, se refere a PHPUnit\Framework\TestCase, ou seja, dentro do callback temos acesso ao mesmo $this que já estamos acostumados no PHPUnit.

Essa ligação (bind) entre a classe TestCase do PHPUnit e o Pest é a ligação padrão. Caso exista outra classe deste tipo que seja necessário utilizar, podemos fazer esta ligação manualmente no arquivo Pest.php

// tests/Pest.php
uses(Tests\TestCase::class)->in('Feature');

Outros tipos de ligações necessárias também podem ser feitas neste arquivo, como a utilização de traits como RefreshDatabase ou coisa parecida. Mais sobre isso pode ser encontrado nesta sessão da documentação oficial.

Elegância e simplicidade

Até este momento conseguimos entender como iniciar com o Pest e escrever um primeiro caso de teste simples.

Apesar de ter menos código escrito em comparação ao PHPUnit, ainda podemos nos livrar destes callbacks que podem não agradar a todos, além disso, também podemos adicionar outros métodos na cadeia de chamadas para tornar o código anda mais expressivo e elegante.

Algumas funcionalidades no PestPHP foram inspiradas pelo Jest como o próprio autor indica nesta parte da documentação oficial, a API de expectations deixa o código de teste ainda mais fluído e pode nos ajudar a remover aqueles callbacks, veja só:

expect(true)
    ->toBe(true);

Com o expect() passamos direto qual a expectativa do teste em questão e temos a possibilidade de encadear outras diretivas para checar o resultado, no caso acima, foi utilizada a diretiva toBe() que serve para verificar se o valor passado é do mesmo tipo e valor que o valor esperado.

Será que ainda dá pra deixar um pouquinho mais legal este código? Podemos utilizar uma diretiva mais específica que o toBe(), como desejamos saber se o valor passado para o expect() é true, podemos utilizar a diretiva toBeTrue():

expect(true)
    ->toBeTrue();

E para finalizar, podemos encadear nossos expect às diretivas it() ou test() para adicionar ainda mais legibilidade aos nossos testes. Vamos ver como ficaria um teste para verificar se true é realmente true:

it('should be true')
    ->expect(true)
    ->toBeTrue();

Ou então:

test('true should be true')
    ->expect(true)
    ->toBeTrue();

Todos estes inputs testarão a mesma coisa: se true é realmente true. A maior diferença está apenas na descrição do output gerado, então podemos escolher a forma que faça mais sentido para nossas convenções de nomes e descrições.

Asserções e Expectativas

Basicamente as asserções que podem ser utilizadas são as mesmas do TestCase que o Pest estará utilizando, o framework fará a “ligação” ao $this da classe TestCase, além disso existem as asserções indicadas na documentação oficial .

As “expectativas” (expectations) como toBe() e toBeTrue() que foram utilizadas nos exemplos e as demais disponíveis no Pest também podem ser consultadas na documentação e quanto mais longe formos na documentação da API de “expectativas”, mais elegante e expressivo nossos testes ficarão, então recomendo fortemente dar uma passada na doc!

Conclusão

A proposta do framework é trazer uma experiência mais fluida e elegante no desenvolvimento de testes e com certeza estes quesitos são muito bem tratados! O output também é muito bacana e traz uma cara nova para o ciclo de desenvolvimento e feedback com testes.

A princípio podem haver algumas dificuldades em encontrar as expectativas (expectations) e asserções que tornem o código de testes realmente mais expressivo mas é apenas uma questão de costume e neste caso a documentação é nossa melhor amiga, e diga-se de passagem: a documentação está muito boa!

Espero ter ajudado a conhecer um pouco mais desta ferramenta e em breve teremos mais posts relacionados ao Pest então se liga na tag Pest aqui do blog.

-- Up the Laravel's \o/

← Post Anterior
Próximo Post →