Reputation: 4114
So I created a custom plugin and implemented unit tests.
So far, it has been easy to add a WooCommerce dependency and a private plugin dependency (Iconic Plugin).
The problem is that Iconic plugin is dependent on WooCommerce. At each test, it thinks that WooCommerce is not activated.
Therefore, it does not instantiate correctly.
Iconic plugin
class Iconic_Private_Plugin() {
/**
* Constructor
*/
public function __construct() {
public $bar;
if ( ! Iconic_Private_Core_Helpers::is_plugin_active( 'woocommerce/woocommerce.php' ) && ! Iconic_Private_Core_Helpers::is_plugin_active( 'woocommerce-old/woocommerce.php' ) ) {
return;
// It stops right here!!!
}
$this->bar = "foo"; // Not assigned!!!
}
}
global $iconic_private_plugin; // Methods can be accessed from global variable $iconic_private_plugin.
$iconic_private_plugin = new Iconic_Private_Plugin();
So here what I did from bash commands, bootstrap & unit tests.
install-wp-tests.sh
install_dependencies() {
WP_SITE_URL="http://localhost:8080"
WP_PLUGIN_DIR=$(pwd)
WP_DB_DATA="$WP_PLUGIN_DIR/tests/data/db.sql"
cd "$WP_CORE_DIR"
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar core config --dbname=$DB_NAME --dbuser=$DB_USER --dbpass=$DB_PASS --dbhost=$DB_HOST --dbprefix=wptests_
php wp-cli.phar db import $WP_DB_DATA
php wp-cli.phar search-replace "http://local.wordpress.test" "$WP_SITE_URL"
php wp-cli.phar theme install twentyseventeen --activate
php wp-cli.phar plugin install https://downloads.wordpress.org/plugin/woocommerce.${WC_VERSION}.zip --activate
php wp-cli.phar plugin install https://downloads.wordpress.org/plugin/posts-to-posts.${P2P_VERSION}.zip --activate
php wp-cli.phar plugin install $WP_PLUGIN_DIR/plugins/iconic-private-plugin.zip --activate
php wp-cli.phar plugin list
}
bootstrap.php
/**
* Setup the unit testing environment.
*/
public function __construct() {
// phpcs:disable WordPress.PHP.DiscouragedPHPFunctions, WordPress.PHP.DevelopmentFunctions
ini_set( 'display_errors', 'on' );
error_reporting( E_ALL );
// phpcs:enable WordPress.PHP.DiscouragedPHPFunctions, WordPress.PHP.DevelopmentFunctions
// Ensure server variable is set for WP email functions.
// phpcs:disable WordPress.VIP.SuperGlobalInputUsage.AccessDetected
if ( ! isset( $_SERVER['SERVER_NAME'] ) ) {
$_SERVER['SERVER_NAME'] = 'localhost';
}
// phpcs:enable WordPress.VIP.SuperGlobalInputUsage.AccessDetected
$this->tests_dir = dirname( __FILE__ );
$this->plugin_dir = dirname( $this->tests_dir );
$this->wp_tests_dir = getenv( 'WP_TESTS_DIR' ) ? getenv( 'WP_TESTS_DIR' ) : rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib';
// load test function so tests_add_filter() is available.
require_once $this->wp_tests_dir . '/includes/functions.php';
// load Dependencies.
tests_add_filter( 'muplugins_loaded', array( $this, 'my_custom_plugin_manually_load_plugin' ) );
// install WC.
tests_add_filter( 'setup_theme', array( $this, 'install_wc' ) );
// load the WP testing environment.
require_once $this->wp_tests_dir . '/includes/bootstrap.php';
}
/**
* Install WooCommerce after the test environment and WC have been loaded.
*/
public function install_wc() {
// Clean existing install first.
define( 'WP_UNINSTALL_PLUGIN', true );
define( 'WC_REMOVE_ALL_DATA', true );
include (ABSPATH . 'wp-content/plugins/woocommerce/uninstall.php');
WC_Install::install();
// Reload capabilities after install, see https://core.trac.wordpress.org/ticket/28374
if ( version_compare( $GLOBALS['wp_version'], '4.7', '<' ) ) {
$GLOBALS['wp_roles']->reinit();
} else {
$GLOBALS['wp_roles'] = null; // WPCS: override ok.
wp_roles();
}
echo esc_html( 'Installing WooCommerce...' . PHP_EOL );
}
/**
* Load Dependencies
*/
public function my_custom_plugin_manually_load_plugin() {
$this->plugins_dir = ABSPATH . str_replace( site_url() . '/', '', plugins_url() ) . '/';
// Load dependencies.
require_once $this->plugins_dir . 'woocommerce/woocommerce.php';
require_once $this->plugins_dir . 'iconic/iconic-private-plugin.php';
// Load plugin.
require_once $this->plugin_dir . '/my-custom-plugin.php';
global $my_custom_plugin;
$my_custom_plugin = new My_Custom_Plugin_Class();
}
My unit tests
<?php
/**
* Sql test case.
*/
class SqlTest extends WP_UnitTestCase {
/**
* Set up fixtures before class for all tests in SqlTest Class.
*
* @param object $factory passed by WP_UnitTestCase.
*/
public static function wpSetUpBeforeClass( $factory ) {
self::createFixtures();
self::createSettings();
}
public function setUp() {
self::set_active_plugins();
}
public static function set_active_plugins() {
activate_plugin(ABSPATH . 'wp-content/plugins/woocommerce/woocommerce.php');
activate_plugin(ABSPATH . 'wp-content/plugins/iconic/iconic-private-plugin.php');
}
/**
* Warehouses fixtures
*/
public static function createFixtures() {
// [...]
}
/**
* Create timeslots
*/
public static function createSettings() {
$settings = array (
// [...]
);
update_option( 'iconic_private_plugin_settings', $settings );
global $iconic_private_plugin;
$iconic_private_plugin->settings = $settings;
}
/**
* Test for custom_function.
*/
public function test_custom_function() {
global $my_custom_plugin, $iconic_private_plugin;
echo $iconic_private_plugin->bar; // Has not been assigned!!! (but it should be.
print_r($iconic_private_plugin);
// Class properties are empty, since construct method stop at WooCommerce activation check. (same as above example)
$this->assertTrue(true);
}
}
As you can see I even tried to activate straight in the database the plugins between each test (setUp function).
So i guess the problem could come from bootstrap.php
I could not find any documentation or similar issue through the web.
The only thing that was close enough :
WordPress plugin phpunit tests with dependencies
I also get inspired from WooCommerce tests setup.
Any ideas of what i'm doing wrong ?
UPDATE
After T.Todua's answer i have some warnings thrown in the console. However it did solve the dependency's instantiation and tests are working as intended.
But since there are those warnings, i'm wondering if it is the right way to do it and/or how to fix those warnings.
All those warnings seem to be related to Freemius dependency (only putting one here since there are more or less the same).
So probably not related to this issue.
Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
PHP Warning: fopen(/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/iconic-private-plugin.php): failed to open stream: No such file or directory in /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-includes/functions.php on line 4918
PHP Stack trace:
PHP 1. {main}() /usr/local/bin/phpunit:0
PHP 2. PHPUnit\TextUI\Command::main() /usr/local/bin/phpunit:570
PHP 3. PHPUnit\TextUI\Command->run() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:148
PHP 4. PHPUnit\TextUI\Command->handleArguments() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:159
PHP 5. PHPUnit\TextUI\Command->handleBootstrap() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:788
PHP 6. PHPUnit\Util\Fileloader::checkAndLoad() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:991
PHP 7. PHPUnit\Util\Fileloader::load() phar:///usr/local/bin/phpunit/phpunit/Util/Fileloader.php:48
PHP 8. include_once() phar:///usr/local/bin/phpunit/phpunit/Util/Fileloader.php:64
PHP 9. My_Plugin_Unit_Tests_Bootstrap::instance() /Users/brieuc/Workspace/php/my-plugin/web/wp-content/plugins/my-plugin-geo/tests/bootstrap.php:150
PHP 10. My_Plugin_Unit_Tests_Bootstrap->__construct() /Users/brieuc/Workspace/php/my-plugin/web/wp-content/plugins/my-plugin-geo/tests/bootstrap.php:145
PHP 11. require_once() /Users/brieuc/Workspace/php/my-plugin/web/wp-content/plugins/my-plugin-geo/tests/bootstrap.php:80
PHP 12. require_once() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress-tests-lib/includes/bootstrap.php:105
PHP 13. do_action() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-settings.php:295
PHP 14. WP_Hook->do_action() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-includes/plugin.php:453
PHP 15. WP_Hook->apply_filters() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-includes/class-wp-hook.php:310
PHP 16. My_Plugin_Unit_Tests_Bootstrap->load_wds() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-includes/class-wp-hook.php:286
PHP 17. require_once() /Users/brieuc/Workspace/php/my-plugin/web/wp-content/plugins/my-plugin-geo/tests/bootstrap.php:93
PHP 18. jckWooDeliverySlots->__construct() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/iconic-private-plugin.php:3209
PHP 19. jckWooDeliverySlots->load_classes() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/iconic-private-plugin.php:114
PHP 20. Iconic_Private_Core_Licence::run() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/iconic-private-plugin.php:175
PHP 21. Iconic_Private_Core_Licence->__construct() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/class-core-licence.php:49
PHP 22. Iconic_Private_Core_Licence::configure_freemius() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/class-core-licence.php:60
PHP 23. fs_dynamic_init() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/class-core-licence.php:88
PHP 24. Freemius::instance() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/start.php:506
PHP 25. Freemius->__construct() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/includes/class-freemius.php:2217
PHP 26. Freemius->get_plugin_name() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/includes/class-freemius.php:469
PHP 27. Freemius->set_name() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/includes/class-freemius.php:8627
PHP 28. Freemius->get_plugin_data() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/includes/class-freemius.php:8648
PHP 29. get_plugin_data() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-content/plugins/iconic-private-plugin/inc/vendor/freemius/includes/class-freemius.php:8475
PHP 30. get_file_data() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-admin/includes/plugin.php:84
PHP 31. fopen() /private/var/folders/1n/7zbwzbgj1vz7y89rbjb5hg340000gn/T/wordpress/wp-includes/functions.php:4918
Upvotes: 5
Views: 1506
Reputation: 56497
what if you used
private function force_activate( $plugin ) {
if( ! function_exists('activate_plugin') ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if( ! is_plugin_active( $plugin ) ) {
activate_plugin( $plugin );
}
}
...
// Load dependencies.
require_once $this->plugins_dir . 'woocommerce/woocommerce.php';
$this->force_activate('woocommerce/woocommerce.php');
require_once $this->plugins_dir . 'iconic/iconic-private-plugin.php';
Upvotes: 3