J'utilise PHPUnit pour tester un peu mon WP plug-in au-dessus de la suite de tests WP. Tout fonctionne bien sauf que lorsque j'essaie de créer une table via la méthode setUp, la table n'est pas créée.
Voici mon code:
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);
}
}
}
}
La classe PAO_UnitTestCase est simplement une extension de la classe WP_UnitTestCase qui contient une méthode - la méthode el - qui enregistre simplement le contenu dans un fichier de mon choix.
Comme vous pouvez le voir, j’ai utilisé la méthode el pour
Selon le journal, dbDelta a pu créer la table, mais celle-ci ne fait pas partie des tables existantes.
Donc mes questions sont:
J'espère que quelqu'un pourra m'aider.
Merci!
Mise à jour: Comme indiqué dans la discussion et la réponse acceptée ci-dessous, les tables sont créées mais en tant que tables TEMPORARY. Vous ne pourrez pas voir les tables via SHOW TABLES, mais vous vérifiez son existence en insérant une ligne, puis en essayant de la récupérer.
Vous venez de découvrir une fonctionnalité importante de la suite de tests principale: elle force toutes les tables créées lors du test à être des tables temporaires.
Si vous regardez dans la méthode WP_UnitTestCase::setUp()
, vous verrez que il appelle une méthode appelée start_transaction()
. That méthode start_transaction()
démarre une transaction de base de données 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' ) );
}
Ainsi, toutes les modifications apportées par votre test à la base de données peuvent simplement être annulées par la suite dans la méthode tearDown()
. Cela signifie que chaque test commence par une base de données WordPress vierge, non altérée par les tests précédents.
Cependant, vous remarquerez que start_transaction()
rattache également deux méthodes au filtre 'query'
: _create_temporary_tables
et _drop_temporary_tables
. Si vous examinez la source de ces méthodes , vous verrez qu'elles font en sorte que les requêtes de table CREATE
ou DROP
soient plutôt des tables temporaires:
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;
}
Le filtre 'query'
est appliqué à toutes les requêtes de base de données transmises via $wpdb->query()
, que dbDelta()
utilise . Cela signifie donc que lorsque vos tables sont créées, elles le sont sous la forme de tables temporaires.
Donc, afin de lister ces tables, Je pense que vous devriez plutôt afficher les tables temporaires: $sql = "SHOW TEMPORARY TABLES LIKE '%'";
Update: MySQL ne vous permet pas de lister les tables temporaires comme vous pouvez le faire avec les tables normales. Vous devrez utiliser une autre méthode pour vérifier si la table existe, par exemple en essayant d'insérer une ligne.
Mais pourquoi le cas de test unitaire nécessite-t-il la création de tables temporaires? N'oubliez pas que nous utilisons des transactions MySQL pour que la base de données reste propre. Cependant, nous ne voulons pas jamais engager les transactions, nous voulons toujours les annuler à la fin du test. Mais il y a certaines instructions MySQL qui vont causer un implicite commit . Parmi ceux-ci, vous l'avez deviné, CREATE TABLE
et DROP TABLE
. Cependant, selon la documentation MySQL:
Les instructions
CREATE TABLE
etDROP TABLE
ne commettent pas de transaction si le mot cléTEMPORARY
est utilisé.
Par conséquent, pour éviter une validation implicite, le scénario de test force toutes les tables créées ou supprimées à être des tables temporaires.
Ce n'est pas une fonctionnalité bien documentée, mais une fois que vous comprenez ce qui se passe, il devrait être assez facile de travailler avec.