Plugin development with unit tests

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:

Read More
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?

Related posts

Leave a Reply

2 comments

  1. 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' ) );
    
  2. 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.