草庐IT

php - 使用具有嵌套插件依赖项的自定义 wordpress 插件进行单元测试

coder 2024-04-19 原文

所以我创建了一个自定义插件并实现了单元测试。

到目前为止,添加 WooCommerce 依赖项和私有(private)插件依赖项 (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 命令、 Bootstrap 和单元测试中所做的。

安装-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

我无法通过网络找到任何文档或类似问题。

唯一足够接近的东西:

WordPress plugin phpunit tests with dependencies

我也从 WooCommerce 测试中得到启发 setup .

我做错了什么有什么想法吗?

更新

T.Todua's answer 之后我在控制台中抛出了一些警告。 然而,它确实解决了依赖项的实例化问题,并且测试按预期工作。

但由于有这些警告,我想知道这样做是否正确和/或如何修复这些警告。

所有这些警告似乎都与 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

最佳答案

如果你用过会怎样

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

关于php - 使用具有嵌套插件依赖项的自定义 wordpress 插件进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54576630/

有关php - 使用具有嵌套插件依赖项的自定义 wordpress 插件进行单元测试的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  10. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

随机推荐