Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

One of the things that my plugin does is creates a number of SQL tables as part of a versioning function (that is run under the admin_init hook as I couldn't find a better wordpress way of doing things). I call the initialisation script as part of the setUp routine and theorectically should be dropped as part of the tearDown routine.

In essence here is the basic stub of what I'm (unsuccessfully) doing:

class GFDL_test extends WP_UnitTestCase {
public $plugin_slug = 'gfdl';
protected $users = array();

function setUp() {
    parent::setUp();
    include_once(/* path for gfdl_versioning function*/);
    GFDataLayer::init_globals();
    gfdl_versioning(); /* this creates the tables */

    /* add test users (to give them a role add a 'role' parameter to this add user) */
    $this->users[0] = wp_insert_user(array('user_login' => 'test1'));
    $this->users[1] = wp_insert_user(array('user_login' => 'test2'));
}

function tearDown() {
    global $wpdb;
    /* these lines don't work for some reason */
    $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'gfdl_bullets;');
    $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'gfdl_character_ai;');
    $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'gfdl_items;');
    $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'gfdl_sprites;');
    $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'gfdl_backgrounds;');

    wp_delete_user($this->users[0]);
    wp_delete_user($this->users[1]);
    parent::tearDown();
}

function testDatalayer() {
    $this->assertTrue(class_exists( 'GFDataLayer'));
}

function testVersion() {
    $this->assertEquals('0.11', get_option('gfdl_version'));
}
}

The tear down function appears to be executing but the drop tables aren't working (they remain after the unit tests are finished).

My first thought is that the tests were being executed asynchronously but my debugging is suggesting otherwise.

Is there a better way in handling plugin upgrades (in respect to database changes) or is there something that I'm missing?

share|improve this question
    
It is hard to guess reasons for "don't work"... Is code getting executed? Are SQL queries valid? Are they reaching database? etc... –  Rarst May 27 '13 at 13:18
    
As mentioned in the question, the teardown function appears to be executing (at one stage I had an echo statement in the teardown which was echoed to the console that phpunit writing to) but the tables are still there at the end of the test (causing problems when I try to re-create them in the setUp method). –  Brian Barnes May 27 '13 at 21:27

2 Answers 2

up vote 2 down vote accepted

The unit tests transform all CREATE TABLE and DROP TABLE queries to CREATE TEMPORARY TABLE and DROP TEMPORARY TALBE, respectively. So in your tearDown the query will attempt to drop temporary tables with those names, but not the actual tables. To fix this, add this before your DROP queries:

remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );

You may also need to add this before your CREATE TABLE queries:

remove_filter( 'dbdelta_create_queries', array( $this, '_create_temporary_tables' ) );

The WP_UnitTestCase::_create_temporary_tables() function is the one that filters the queries to make tables temporary. It is added in the setUp(), and removed in the tearDown().

Update:

The _create_temporary_tables() function is now hooked to the 'query' filter, instead of 'dbdelta_create_queries'. See changeset 27041. So now to remove it you would do:

remove_filter( 'query', array( $this, '_create_temporary_tables' ) );
share|improve this answer
    
As is, it isn't working for me. I'm wondering if that is something to do with $this not being an instance of WP_UnitTestCase ($this is an object that is inherited from it). If I move parent::tearDown(); above the drop table statements, they work, but I'm worried about other effects. –  Brian Barnes Sep 24 '13 at 5:07
    
Ahh... you need to use remove_filter( 'query', array( $this, '_drop_temporary_tables' ) ); too. I've updated my answer. ` –  J.D. Sep 24 '13 at 13:04

Have you tried to execute the SQL statements manually ? You would perhaps see an error message preventing the table DROP command to execute (like insufficient rights).

Normally, the SQL tables creating is done in the activation hook and SQL tables drops in deactivation hook.

And yes, WP has a mechanism to automatically update tables structure based on the plugin version number.

share|improve this answer
    
The drop table SQL worked fine (assuming I got $wpdb->prefix right). Rights is not an issue as I'm running the queries as root (it is on my local machine). That mechanism seems fine for the structure, but I'm not sure how it would handle changing data inside the tables (for testing purposes). Upvoted as it is a good way of how things should be done. –  Brian Barnes Jul 2 '13 at 0:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.