Teste da Unidade WordPress – Não é possível criar tabelas

Estou usando PHPUnit para Unit Testar meu plug-in WP em cima do conjunto de testes WP. Tudo funciona bem, exceto que quando eu tento criar uma tabela através do método setUp, a tabela não é criada.

Aqui está o meu código:

class Test_Db extends PAO_UnitTestCase { function setUp() { parent::setUp(); global $wpdb; $sql = "CREATE TABLE {$wpdb->prefix}mytest ( id bigint(20) NOT NULL AUTO_INCREMENT, column_1 varchar(255) NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $this->el(dbDelta($sql)); } function tearDown() { parent::tearDown(); } function test_db_stuff(){ global $wpdb; $sql = "SHOW TABLES LIKE '%'"; $results = $wpdb->get_results($sql); foreach($results as $index => $value) { foreach($value as $tableName) { $this->el($tableName); } } } } 

A class PAO_UnitTestCase é simplesmente uma extensão da class WP_UnitTestCase que contém um método – o método el – que simplesmente registra tudo em um arquivo da minha escolha.

Como você pode ver, usei o método para

  1. Escreva a resposta do dbDelta no log
  2. Escreva os nomes de todas as tabelas existentes no log

De acordo com o registro, dbDelta conseguiu criar a tabela, mas não está sendo listado como parte das tabelas existentes.

Então minhas perguntas são:

  1. É possível criar tabelas durante o teste de unidade via PHPUnit?
  2. Em caso afirmativo, o que estou fazendo de errado?

Espero que alguém possa me ajudar.

Obrigado!

Atualização: conforme visto na discussão e na resposta aceita abaixo, as tabelas são criadas, mas como tabelas TEMPORÁRIAS. Você não poderá ver as tabelas através de SHOW TABLES, mas você verificará sua existência inserindo uma linha e tentando recuperar a linha.

Solutions Collecting From Web of "Teste da Unidade WordPress – Não é possível criar tabelas"

Você acabou de descobrir uma característica importante do conjunto de testes principais: força as tabelas criadas durante o teste a serem tabelas temporárias.

Se você olhar no WP_UnitTestCase::setUp() , você verá que ele chama um método chamado start_transaction() . Esse método start_transaction() inicia uma transação de database MySQL :

  function start_transaction() { global $wpdb; $wpdb->query( 'SET autocommit = 0;' ); $wpdb->query( 'START TRANSACTION;' ); add_filter( 'query', array( $this, '_create_temporary_tables' ) ); add_filter( 'query', array( $this, '_drop_temporary_tables' ) ); } 

Isso faz isso para que qualquer alteração que o teste faça no database possa ser revertida posteriormente no método tearDown() . Isso significa que cada teste começa com um database WordPress limpo, não mantido pelos testes anteriores.

No entanto, você start_transaction() que start_transaction() também gera dois methods para o filtro 'query' : _create_temporary_tables e _drop_temporary_tables . Se você olhar para a fonte desses methods , verá que eles causam que as consultas da tabela CREATE ou DROP sejam para tabelas temporárias em vez disso:

  function _create_temporary_tables( $query ) { if ( 'CREATE TABLE' === substr( trim( $query ), 0, 12 ) ) return substr_replace( trim( $query ), 'CREATE TEMPORARY TABLE', 0, 12 ); return $query; } function _drop_temporary_tables( $query ) { if ( 'DROP TABLE' === substr( trim( $query ), 0, 10 ) ) return substr_replace( trim( $query ), 'DROP TEMPORARY TABLE', 0, 10 ); return $query; } 

O filtro 'query' é aplicado a todas as consultas de database passadas através de $wpdb->query() , que usa dbDelta() . Isso significa que quando suas tabelas são criadas, elas são criadas como tabelas temporárias .

Então, para listar essas tabelas, Eu acho que você precisaria mostrar tabelas temporárias em vez disso: $sql = "SHOW TEMPORARY TABLES LIKE '%'";

Atualização: o MySQL não permite que você liste as tabelas temporárias como você pode com as tabelas normais. Você terá que usar outro método para verificar se a tabela existe, como tentar inserir uma linha.

Mas por que o caso de teste da unidade exige tabelas temporárias para serem criadas em primeiro lugar? Lembre-se de que estamos usando transactions MySQL para que o database fique limpo. Nós não queremos nunca comprometer as transactions, porém, queremos sempre devolvê-las no final do teste. Mas existem algumas declarações MySQL que irão causar um commit implícito . Entre estes, você adivinhou, CREATE TABLE e DROP TABLE . No entanto, de acordo com os documentos do MySQL:

CREATE TABLE e DROP TABLE não confirmam uma transação se a palavra-chave TEMPORARY for usada.

Portanto, para evitar uma confirmação implícita, o caso de teste força as tabelas criadas ou descartadas para serem tabelas temporárias.

Esta não é uma característica bem documentada, mas uma vez que você entende o que está acontecendo deve ser muito fácil de trabalhar.