Модульные тесты с пользовательским плагином WordPress, имеющим вложенные зависимости плагина

Поэтому я создал собственный плагин и реализовал модульные тесты.

До сих пор было легко добавить зависимость WooCommerce и зависимость частного плагина (Iconic Plugin).

Проблема в том, что плагин Iconic зависит от WooCommerce. При каждом тесте думает, что WooCommerce не активирован.

Следовательно, он не создает экземпляр правильно.

Знаковый плагин

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();

Итак, вот что я сделал из команд bash, начальной загрузки и модульных тестов.

установка-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();
}

Мои модульные тесты

<?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);
    }

}

Как видите, я даже пытался активировать плагины прямо в базе данных между каждым тестом (функция setUp).

Так что я предполагаю, что проблема может исходить от bootstrap.php

Я не смог найти какую-либо документацию или аналогичную проблему в Интернете.

Единственное, что было достаточно близко:

Тесты phpunit плагина WordPress с зависимостями

Меня также вдохновляют тесты WooCommerce настраивать.

Любые идеи о том, что я делаю неправильно?

ОБНОВИТЬ

После Ответ Т.Тодуа у меня в консоли появилось несколько предупреждений. Однако он разрешил создание экземпляра зависимости, и тесты работают по назначению.

Но поскольку есть эти предупреждения, мне интересно, правильно ли это сделать и/или как исправить эти предупреждения.

Все эти предупреждения, похоже, связаны с зависимостью от Freemius (здесь указано только одно, поскольку они более или менее одинаковы).

Так что скорее всего не в этом вопросе.

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

Соглашаться! Но... Функции, которые необходимо протестировать, вызывают несколько функций из этой зависимости. Я с трудом понимаю, как я мог издеваться над этим, а затем поддерживать его.

Brieuc 14.02.2019 13:59

так что это не unitTest, это функциональный тест

DevDonkey 14.02.2019 14:14

Возможно ли, что файл плагина уже был включен до того, как вы set_active_plugin? Если это так, класс плагина может быть создан без активной woocommerce. Проверьте, что включено в php.net/manual/en/function.get-included-files.php в set_active_plugin до activate_plugin(ABSPATH . 'wp-content/plugins/iconic/iconic-private-plugin.php');.

Andrew 15.02.2019 11:29

@DevDonkey Вы правы, этот конкретный тест был бы скорее функциональным тестом. Я бы предпочел модульные тесты, но не думаю, что смогу издеваться над зависимостью. Спасибо за вклад :).

Brieuc 18.02.2019 10:03

@Эндрю, это было, и я не смог активировать плагин с помощью этого хука. Но, как ответил T.Todua, eequiring wp-admin/includes/plugin.php сделал свое дело (по крайней мере, чтобы активировать WooCommerce, прежде чем требовать другой плагин.

Brieuc 18.02.2019 10:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
5
835
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

что, если бы вы использовали

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';

Кажется, это поможет ;). Кажется, плагин хорошо реализован. У меня есть некоторые другие ошибки, которые выдаются на данный момент, но я собираюсь убедиться, что это не связано.

Brieuc 18.02.2019 09:59

@Brieuc Я думаю, что это другой случай. вам лучше открыть новый вопрос для этого с конкретным названием. И желательно в с.тк/вп

T.Todua 18.02.2019 13:26

Спасибо! У меня были некоторые сомнения по этому поводу :).

Brieuc 18.02.2019 13:29

Другие вопросы по теме