Getting around a Codeception issue in WordPress “unit” tests.
The problem
I keep running on this issue now and then especially when testing plugins or themes that require a fixture to be in place using the WP Browser module for Codeception.
Given the typical Codeception tests folder structure
/src
/tests
_bootstrap.php <<< loaded
/acceptance
_bootstrap.php
/functional
_bootstrap.php <<< not loaded
/unit
_bootstrap.php
adding set up methods in the bootstrap file marked “not loaded” will not work.
Ideally, I’m using the latest plugin I’m developing as an example, the /tests/functional/_bootstrap.php
file should contain this
<?php
// Here you can initialize variables that will be available to your tests
// register the taxonomy the plugin will use
tests_add_filter('init', function(){
register_taxonomy( 'user-group', 'user' );
});
// activate the plugin
activate_plugin( 'user-groups-content-restriction/user-groups-content-restriction.php' );
and the test case should run after the global and the functional _bootstrap.php
files have been included.
<?php
class ugcr_TermManagerTest extends \WP_UnitTestCase {
protected $backupGlobals = false;
/**
* @var ugcr_TermManager
*/
protected $sut;
public function setUp() {
// before
parent::setUp();
// your set up methods here
$this->sut = new ugcr_TermManager();
}
public function tearDown() {
// your tear down methods here
// then
parent::tearDown();
}
/**
* @test
* it should add all the terms on activation if none present
*/
public function it_should_add_all_the_terms_on_activation_if_none_present() {
$terms = $this->sut->get_terms();
$this->assertCount( 0, get_terms( 'user-group' ) );
$this->sut->insert_terms();
$this->assertCount( count( $terms ), get_terms( 'user-group', [ 'hide_empty' => false ] ) );
}
}
This will not work at the moment and the issue is a known one. The Codeception team has proved amazing and will fix the issue as soon as they have the energy to do so.
Fix
That’s not always the case and will not work if the plugin has critical operations tied to WordPress hooks like init
but will work in this specific case; the code that should be executed in the _bootstrap.php
file I ’ve simply moved to the setUp
method of the test case:
<?php
class ugcr_TermManagerTest extends \WP_UnitTestCase {
protected $backupGlobals = false;
/**
* @var ugcr_TermManager
*/
protected $sut;
public function setUp() {
// before
parent::setUp();
// your set up methods here
activate_plugin( 'user-groups-content-restriction/user-groups-content-restriction.php' );
register_taxonomy( 'user-group', 'user' );
$this->sut = new ugcr_TermManager();
}
public function tearDown() {
// your tear down methods here
// then
parent::tearDown();
}
/**
* @test
* it should add all the terms on activation if none present
*/
public function it_should_add_all_the_terms_on_activation_if_none_present() {
$terms = $this->sut->get_terms();
$this->assertCount( 0, get_terms( 'user-group' ) );
$this->sut->insert_terms();
$this->assertCount( count( $terms ), get_terms( 'user-group', [ 'hide_empty' => false ] ) );
}
}