Teste Unitário no PHPUnit para aplicar em arquivos do Magento 2
Lucas Teixeira dos Santos Santana
Posted on October 14, 2022
PHPUnit
O PHPUnit é uma ferramenta de testes de unidade que disponibiliza um ecossistema necessário para realizar testes de forma automatizada em PHP. O PHPUnit está disponível para aplicações com o PHP a partir da versão 5.5.
Ele é instalado como uma dependência ao projeto e se adéqua com a estrutura do mesmo. Possui uma CLI (Interface de Linha de Comando) própria com opções de personalização para a forma de executar os testes.
O PHPUnit é baseado na ideia que o desenvolvedor deve encontrar erros no código-fonte o mais rápido possível. Semelhante a outros frameworks de teste unitário, ele usa assertions para verificar se o código-fonte está se comportando como o esperado.
Também suporta a declaração de dependências explícitas entre métodos de teste. Tais dependências não definem a ordem em que os métodos de teste devem ser executados, mas permitem o retorno de uma instância do ambiente do teste por um produtor e a passagem dele para os consumidores dependentes.
Para executar os testes com o PHPUnit, deve-se chamar o comando phpunit
que estará dentro de ./vendor/bin/phpunit
e referenciar o arquivo phpunit.xml
com as configurações que serão utilizados para a execução dos testes.
O Magento 2 por padrão já possui um arquivo phpunit.xml
que pode ser utilizado, ele se encontra no caminho ./dev/tests/unit/phpunit.xml.dist
. O terceiro argumento passado no comando para a execução de testes será o caminho do módulo.
./vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist app/code/{Vendor}/{Module}
./vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist vendor/{vendor}/{module}
phpunit.xml
Caso seja necessário personalizar a execução de testes (exemplo: ignorar a pasta API do módulo) é possível criar um arquivo phpunit.xml
no próprio módulo e configurar para que os testes sejam executados de acordo com a configuração deste arquivo.
./vendor/bin/phpunit -c app/code/{Vendor}/{Module}/phpunit.xml.dist app/code/{Vendor}/{Module}
./vendor/bin/phpunit -c vendor/{vendor}/{module}/phpunit.xml.dist vendor/{vendor}/{module}
Código base para a implantação
Para escrever testes com o PHPUnit no Magento 2 basta criar a estrutura de pastas \{Vendor}\{Module}\Test\Unit\{ClassDirectory}\{ClassName}Test
estender a classe que \PHPUnit\Framework\TestCase
. O PHPUnit localiza os métodos de teste pelo prefixo test
no nome do método, e neste contém asserções para validar que o método retorne um valor real equivalente ao esperado.
Classe a ser testada:
<?php
namespace {Vendor}\{Module}\{ClassDirectory};
class {ClassName}
{
public function {methodName}(): {type}
{
// Code here
}
}
Classe de teste:
<?php
namespace {Vendor}\{Module}\Test\Unit\{ClassDirectory};
use PHPUnit\Framework\TestCase;
class {ClassName}Test extends TestCase
{
public function test{MethodName}(): {type}
{
// Code here
}
}
Asserções
Asserções são métodos desenvolvidos pelo PHPUnit para assegurar que o valor de um teste é um valor esperado, ou seja, sãos métodos que executam a unidade e certificam que o resultado gerado no teste é o esperado com sucesso ou falham.
Os métodos da classe \PHPUnit\Framework\TestCase
que começam com o prefixo assert, são parte importante dos casos de teste e avaliam se certas condições, decisivas para determinar o sucesso ou falha do teste, geram um resultado esperado.
<?php
namespace {Vendor}\{Module}\Test\Unit\{ClassDirectory};
use PHPUnit\Framework\TestCase;
class {ClassName}Test extends TestCase
{
public function test{MethodName}(): {type}
{
// Code here
$this->assert{Name}({condition});
}
}
É possível verificar a documentação com todas as asserções fornecidas pelo PHPUnit no link “Asserções do PHPUnit“.
Exceções
Usando o método expectException()
, o PHPUnit verifica se durante a exceção do teste é lançada uma exceção dentro do código testado. Além do método expectException()
os métodos expectExceptionCode()
, expectExceptionMessage()
e expectExceptionMessageRegExp()
existem para configurar expectativas de exceções lançadas pelo código sob teste.
<?php
namespace {Vendor}\{Module}\Test\Unit\{ClassDirectory};
use PHPUnit\Framework\TestCase;
class {ClassName}Test extends TestCase
{
public function test{MethodName}(): {type}
{
$this->expectException(\Exception::class);
// Code here
}
}
Provedor de Dados
Com um método provedor de dados (data provider) o PHPUnit permite que o um método de teste seja executado em diferentes cenários, ou seja, consiste em preparar os dados de entradas para que o teste seja executado diversas vezes com dados diferentes.
Um método provedor de dados deve ser do tipo public
, possuir a anotação @dataProvider
como o nome do método e retornar um array de arrays. Cada item do array de retorno, o método de teste chamara como argumento.
<?php
namespace {Vendor}\{Module}\Test\Unit\{ClassDirectory};
use PHPUnit\Framework\TestCase;
class {ClassName}Test extends TestCase
{
/**
* @dataProvider {dataProviderName}
*/
public function test{MethodName}({type} $data): {type}
{
// Code to test here
}
public function {dataProviderName}(): array
{
// Code to provide different input data
return [
[$data1],
[$data2],
[$data3],
...
[$dataN]
];
}
}
Métodos setUp e tearDown
O PHPUnit suporta compartilhamento do código de configuração. Os métodos-modelo setUp()
e tearDown()
são executados uma vez para cada método de teste (e em novas instâncias) da classe do caso de teste. Ambos os métodos devem ser do tipo protected
e não possuir nenhum dado de retorno (void
).
Antes que um método seja executado, um método modelo chamado setUp()
é invocado. O método setUp()
é onde os objetos que serão alvo dos testes são criados.
Uma vez que o método de teste tenha terminado sua execução, seja bem-sucedido ou falho, outro método modelo é invocado tearDown()
. O método tearDown()
é onde os objetos que foram alvo dos testes são limpos, normalmente, implementa-se o método tearDown()
ao alocar recursos externos como arquivos ou sockets no setUp()
.
<?php
namespace {Vendor}\{Module}\Test\Unit\{ClassDirectory};
use PHPUnit\Framework\TestCase;
class {ClassName}Test extends TestCase
{
protected function setUp(): void
{
// Code to set up test objects
}
protected function tearDown(): void
{
// Code to tear down test object
}
public function test{MethodName}(): {type}
{
// Code to test here
}
}
Dublê de Testes
É possível verificar a documentação com tudo sobre os dublês de testes do PHPUnit no link “Dublês de Testes do PHPUnit“.
Os métodos createMock($type)
e getMockBuilder($type)
fornecidos pelo PHPUnit podem ser usados em um teste para gerar automaticamente um objeto que possa atuar como um dublê de teste para a classe original especificada. Esse objeto de dublê de teste pode ser usado em cada contexto onde um objeto da classe original é esperado ou requerido.
$this->createMock({Class}::class)
: este método retorna um objeto de dublê de teste para o tipo especificado (interface ou classe). A criação desse dublê de teste é realizada usando os padrões de boas práticas (os métodos __construct()
e __clone()
da classe original não são executados) e os argumentos passados para um método do dublê de teste não serão clonados.
$this->getMockBuilder({Class}::class)
: este método serve para customizar a geração do dublê de teste usando uma interface fluente. Por padrão, todos os métodos da classe original são substituídos com uma implementação simulada que apenas retorna null
(sem chamar o método original). É possível configurar essas implementações simuladas para retornar um valor quando chamadas.
-
setMethods(array $methods)
: pode ser chamado no objetogetMockBuilder()
para especificar os métodos que devem ser substituídos com um dublê de teste configurável. O comportamento dos outros métodos não muda. Se você chamarsetMethods(null)
, então nenhum dos métodos serão substituídos (utilizado até a versão 7.3.X do PHP); -
onlyMethods(array $methods)
: pode ser chamado no objetogetMockBuilder()
para especificar os métodos que devem ser substituídos por um dublê de teste configurável. O comportamento dos outros métodos não muda. Cada método deve existir na classe que está sendo criada como dublê de teste (utilizado a partir da versão 7.4.X do PHP); -
addMethods(array $methods)
: pode ser chamado no objetogetMockBuilder()
para especificar os métodos que não existem (ainda) na classe de dublê de teste. O comportamento dos outros métodos permanece o mesmo (utilizado a partir da versão 7.4.X do PHP); -
setConstructorArgs(array $args)
: pode ser chamado para fornecer um vetor de parâmetros que é passado ao construtor da classe original (que por padrão não é substituído com uma implementação falsa); -
setMockClassName($name)
: pode ser usado para especificar um nome de classe para a classe de dublê de teste gerada; -
disableOriginalConstructor()
: pode ser usado para desabilitar a chamada ao construtor da classe original; -
disableOriginalClone()
: pode ser usado para desabilitar a chamada ao construtor clone da classe original; -
disableAutoload()
: pode ser usado para desabilitar o__autoload()
durante a geração da classe de dublê de teste.
$this->method('{methodName}')
: o método method('{methodName}')
recebe o nome do método que será testado na classe é tera um retorno void
.
$this->method('{methodName}')->willReturn('{valueToReturn}')
: o método method('{methodName}')
recebe o nome do método que será testado na classe. O método willReturn('{valueToReturn}')
retorna um valor simples para corresponder ao teste, esta sintaxe é o mesmo que $this->method('{methodName}')->will($this->returnValue($value))
.
$this->method('{methodName}')->returnSelf()
: este método retorna o próprio objeto de dublê de teste.
$objectMock->expects($this->once())->method('{methodName}')->with($this->equalTo('something'))
: verifica se um método foi chamado, e com quais argumentos foi chamado, os métodos expects()
e with()
são para especificar como essa interação deve se parecer.
O método with()
pode receber qualquer número de argumentos, correspondendo ao número de argumentos sendo falsos. É possível especificar restrições mais avançadas do que uma simples igualdade no argumento do método.
Posted on October 14, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.