Estou desenvolvendo um plugin usando TDD e uma coisa que eu falho completamente ao testar são ... ganchos.
Quero dizer OK, posso testar o retorno de chamada do gancho, mas como eu poderia testar se um gancho realmente é acionado (ganchos personalizados e ganchos padrão do WordPress)? Suponho que algumas zombarias ajudem, mas simplesmente não consigo descobrir o que estou perdendo.
Eu instalei o conjunto de testes com o WP-CLI. De acordo com esta resposta , o init
gancho deve ser acionado, mas ... não é; Além disso, o código funciona dentro do WordPress.
Pelo que entendi, o bootstrap é carregado por último, então faz sentido não acionar o init, então a questão que permanece é: como diabos devo testar se os ganchos são acionados?
Obrigado!
O arquivo de inicialização aparece assim:
$_tests_dir = getenv('WP_TESTS_DIR');
if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
function _manually_load_plugin() {
require dirname( __FILE__ ) . '/../includes/RegisterCustomPostType.php';
}
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
require $_tests_dir . '/includes/bootstrap.php';
O arquivo testado fica assim:
class RegisterCustomPostType {
function __construct()
{
add_action( 'init', array( $this, 'register_post_type' ) );
}
public function register_post_type()
{
register_post_type( 'foo' );
}
}
E o teste em si:
class CustomPostTypes extends WP_UnitTestCase {
function test_custom_post_type_creation()
{
$this->assertTrue( post_type_exists( 'foo' ) );
}
}
Obrigado!
fonte
phpunit
, consegue ver os testes reprovados ou com falha? Você instaloubin/install-wp-tests.sh
?RegisterCustomPostType::__construct()
nunca seja chamado quando o plug-in é carregado para os testes. Também é possível que você esteja sendo afetado pelo bug # 29827 ; talvez tente atualizar sua versão do conjunto de testes de unidade do WP.bin/install-wp-tests.sh
(desde que eu usei wp-cli) @JD: RegisterCustomPostType :: __ construct é chamado (apenas acrescentou umadie()
declaração e phpunit pára por aí)did_action()
para verificar se as ações foram acionadas.init
gancho).Respostas:
Teste isolado
Ao desenvolver um plugin, a melhor maneira de testá-lo é sem carregar o ambiente WordPress.
Se você escrever um código que possa ser facilmente testado sem o WordPress, seu código se tornará melhor .
Todo componente que é testado em unidade deve ser testado isoladamente : ao testar uma classe, você só precisa testar essa classe específica, assumindo que todos os outros códigos estejam funcionando perfeitamente.
Esta é a razão pela qual os testes de unidade são chamados de "unidade".
Como um benefício adicional, sem carregar o núcleo, seu teste será executado muito mais rápido.
Evite ganchos no construtor
Uma dica que posso lhe dar é evitar colocar ganchos nos construtores. Essa é uma das coisas que tornará seu código testável isoladamente.
Vamos ver o código de teste no OP:
E vamos supor que esse teste falhe . Quem é o culpado ?
Como pode ser melhorado?
Vamos supor que seu código de classe seja:
(Nota: vou me referir a esta versão da turma pelo restante da resposta)
A maneira como escrevi essa classe permite criar instâncias da classe sem chamar
add_action
.Na classe acima, há duas coisas a serem testadas:
init
realmente chamaadd_action
passando a ele argumentos adequadosregister_post_type
realmente chamaregister_post_type
funçãoEu não disse que você precisa verificar se o tipo de postagem existe: se você adicionar a ação apropriada e se ligar
register_post_type
, o tipo de postagem personalizado deverá existir: se não existir, será um problema no WordPress.Lembre-se: ao testar seu plug-in, você deve testar seu código, não o código do WordPress. Nos seus testes, você deve assumir que o WordPress (como qualquer outra biblioteca externa que você usa) funciona bem. Esse é o significado do teste de unidade .
Mas ... na prática?
Se o WordPress não estiver carregado, se você tentar chamar os métodos de classe acima, você receberá um erro fatal e precisará zombar das funções.
O método "manual"
Claro que você pode escrever sua biblioteca de zombaria ou zombar "manualmente" de todos os métodos. É possível. Vou lhe dizer como fazer isso, mas depois mostrarei um método mais fácil.
Se o WordPress não for carregado enquanto os testes estiverem sendo executados, significa que você pode redefinir suas funções, por exemplo,
add_action
ouregister_post_type
.Vamos supor que você tenha um arquivo carregado a partir do seu arquivo de inicialização, onde você tem:
Reescrevi as funções para simplesmente adicionar um elemento a uma matriz global toda vez que elas são chamadas.
Agora você deve criar (se ainda não tiver um) sua própria classe de caso de teste de base estendendo
PHPUnit_Framework_TestCase
: isso permite que você configure facilmente seus testes.Pode ser algo como:
Dessa forma, antes de cada teste, o contador global é redefinido.
E agora seu código de teste (refiro-me à classe reescrita que publiquei acima):
Você deve observar:
Bom .. mas é uma PITA!
Sim, se você precisar zombar manualmente de todas as funções do WordPress, é realmente uma dor. Um conselho geral que posso dar é usar o menor número possível de funções WP: você não precisa reescrever o WordPress, mas funções abstratas do WP que você usa em classes personalizadas, para que possam ser ridicularizadas e facilmente testadas.
Por exemplo, no exemplo acima, você pode escrever uma classe que registra os tipos de postagem, chamando
register_post_type
'init' com os argumentos fornecidos. Com essa abstração, você ainda precisa testar essa classe, mas em outros locais do seu código que registram tipos de postagem, você pode fazer uso dessa classe, zombando dela em testes (supondo que ela funcione).O mais impressionante é que, se você escrever uma classe que abstraia o registro do CPT, poderá criar um repositório separado para ela e, graças a ferramentas modernas como o Composer, ele será incorporado em todos os projetos onde você precisar: teste uma vez, use em qualquer lugar . E se você encontrar um bug nele, poderá corrigi-lo em um só lugar e com um simples
composer update
todos os projetos em que ele é usado também serão corrigidos.Pela segunda vez: escrever código testável isoladamente significa escrever código melhor.
Mas mais cedo ou mais tarde eu preciso usar as funções do WP em algum lugar ...
Claro. Você nunca deve agir paralelamente ao núcleo, não faz sentido. Você pode escrever classes que agrupam as funções do WP, mas essas classes também precisam ser testadas. O método "manual" descrito acima pode ser usado para tarefas muito simples, mas quando uma classe contém muitas funções do WP, pode ser uma dor.
Felizmente, lá existem pessoas boas que escrevem coisas boas. A 10up , uma das maiores agências de WP, mantém uma biblioteca muito boa para pessoas que desejam testar plugins da maneira certa. É
WP_Mock
.Ele permite que você zombe das funções do WP e ganchos . Supondo que você tenha carregado em seus testes (consulte o repositório leia-me), o mesmo teste que escrevi acima se torna:
Simples, não é? Esta resposta não é um tutorial para
WP_Mock
, então leia o readme do repositório para obter mais informações, mas o exemplo acima deve ser bem claro, eu acho.Além disso, você não precisa escrever nenhuma zombaria
add_action
ouregister_post_type
sozinho, nem manter nenhuma variável global.E aulas WP?
O WP também tem algumas classes e, se o WordPress não estiver carregado ao executar testes, você precisará zombar delas.
Isso é muito mais fácil do que zombar de funções, o PHPUnit possui um sistema incorporado para zombar de objetos, mas aqui quero sugerir o Mockery para você. É uma biblioteca muito poderosa e muito fácil de usar. Além disso, é uma dependência de
WP_Mock
, portanto, se você o tiver, também terá Zombaria.Mas que tal
WP_UnitTestCase
?O conjunto de testes do WordPress foi criado para testar o núcleo do WordPress e, se você quiser contribuir com o núcleo, é essencial, mas usá-lo para plug-ins faz com que você não teste isoladamente.
Coloque seus olhos no mundo do WP: existem muitas estruturas PHP modernas e CMS por aí e nenhuma delas sugere testar plugins / módulos / extensões (ou como eles são chamados) usando o código da estrutura.
Se você sente falta de fábricas, um recurso útil da suíte, precisa saber que há coisas incríveis por lá.
Pegadinhas e desvantagens
Há um caso em que o fluxo de trabalho que sugeri aqui não possui: teste de banco de dados personalizado .
De fato, se você usar tabelas e funções padrão do WordPress para escrever lá (nos
$wpdb
métodos de nível mais baixo ), nunca precisará realmente escrever dados ou testar se os dados estão realmente no banco de dados, apenas certifique-se de que os métodos adequados sejam chamados com argumentos adequados.No entanto, você pode escrever plug-ins com tabelas e funções personalizadas que criam consultas para serem escritas lá e testar se essas consultas funcionam, é de sua responsabilidade.
Nesses casos, a suíte de testes do WordPress pode ajudá-lo muito, e o carregamento do WordPress pode ser necessário em alguns casos para executar funções como
dbDelta
.(Não é necessário dizer para usar um db diferente para testes, não é?)
Felizmente, o PHPUnit permite que você organize seus testes em "suítes" que podem ser executadas separadamente, para que você possa criar um conjunto para testes de banco de dados personalizados, onde você carrega o ambiente WordPress (ou parte dele), deixando todo o restante dos testes sem WordPress .
Apenas certifique-se de escrever classes que abstraiam o maior número possível de operações de banco de dados, de maneira que todas as outras classes de plug-ins as utilizem, para que, usando o mock, você possa testar adequadamente a maioria das classes sem lidar com o banco de dados.
Pela terceira vez, escrever código facilmente testável isoladamente significa escrever código melhor.
fonte