tl;dr: is there a way to make changes to WordPress options during a PHPUnit test suite execution, and have the changes reverted to the WordPress defaults before the next test suite is executed, without writing a custom teardown function?
我正在测试我的插件,它提供了一个功能,可以一次添加和删除一些角色。我的插件的用户应该只需运行此功能一次,但他们可以选择根本不运行它,因此我设置了两个测试套件(使用WP-CLI的脚手架)来测试转换角色前后的情况。由于角色转换操作对数据库进行了更改,因此我将对已转换角色的测试分离到各自的PHPUnit组中,并在默认情况下排除了该组的运行。为了测试角色转换函数,我必须调用PHPUnit
--group role-permissions
旗帜我还可以在没有组的情况下调用PHPUnit,在默认WordPress角色上运行测试。
I run into a problem when I run the tests one after the other.
首先,如果我运行默认测试。。。
$> phpunit
[passes]
。。。它们最初通过。如果我运行特殊角色测试。。。
$> phpunit --group role-permissions
[passes]
。。。然后他们也通过了。但如果在此之后再次运行默认测试。。。
$> phpunit
[fails]
。。。它们不再通过。我发现这是因为
role-permissions
在再次运行默认测试之前,测试仍存在于测试数据库中。让默认测试再次通过的唯一方法是重新生成默认WordPress测试数据库。
转换角色以便运行role-permissions
测试,我有一些代码wpSetUpBeforeClass
. 在测试运行之前,每次PHPUnit执行只运行一次,因此这似乎是放置代码的正确位置。然而,很明显,测试脚手架代码并没有恢复默认值wptests_options
每次运行后的数据库表。
在我的特殊测试运行后,是否有方法恢复数据库中的默认选项,或者运行role-permissions
在他们自己的数据库中进行测试,或者以其他方式防止我遇到的故障?
相关文件的精简版本如下所示,以供参考:
tests/test-default-roles.php
:
/**
* // no special group
*/
class OtherTests extends WP_UnitTestCase {
public function test_default_roles() {
// test stuff with the default WordPress roles
}
}
tests/test-new-roles.php
:
/**
* @group role-permissions
*/
class RoleTests extends WP_UnitTestCase {
/**
* Convert roles before running any test
* (this changes the wp_settings table)
*/
public static function wpSetUpBeforeClass( $factory ) {
// convert roles
global $my_tool;
$my_tool->convert_roles();
}
public function test_new_roles() {
// test some stuff to do with the converted roles
}
}
phpunit.xml
...
<testsuites>
<testsuite>
<directory prefix="test-" suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<!-- exclude role conversion tests from running by default -->
<group>role-permissions</group>
</exclude>
</groups>
...
SO网友:Sean
在马克·卡普伦的评论之后,我在WordPress测试源代码中做了一些挖掘,发现_delete_all_data
function 每次测试后运行:
function _delete_all_data() {
global $wpdb;
foreach ( array(
$wpdb->posts,
$wpdb->postmeta,
$wpdb->comments,
$wpdb->commentmeta,
$wpdb->term_relationships,
$wpdb->termmeta,
) as $table ) {
$wpdb->query( "DELETE FROM {$table}" );
}
foreach ( array(
$wpdb->terms,
$wpdb->term_taxonomy,
) as $table ) {
$wpdb->query( "DELETE FROM {$table} WHERE term_id != 1" );
}
$wpdb->query( "UPDATE {$wpdb->term_taxonomy} SET count = 0" );
$wpdb->query( "DELETE FROM {$wpdb->users} WHERE ID != 1" );
$wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE user_id != 1" );
}
如您所见,此功能仅还原(从技术上删除)删除帖子、评论、术语和用户。选项和其他站点配置内容不会还原。
我发现解决问题的方法是在更改角色选项之前对其进行备份,然后将其还原。这不是我想要的解决方案,但似乎是最好的解决方案。首先,我定义了在所有测试运行之前和之后运行一次的类设置和拆卸方法:
public static function wpSetUpBeforeClass( $factory ) {
self::convert_roles();
}
public static function wpTearDownAfterClass() {
self::reset_roles();
}
然后我定义了创建新角色的函数,并在之前将它们重置为默认值。对于这些,我需要在类中定义一些静态变量。
/**
* Convert user roles for the tests in this class.
*
* This only works when the current blog is the one being tested.
*/
private static function convert_roles() {
global $wpdb, $my_tool;
// role settings name in options table
self::$role_key = $wpdb->get_blog_prefix( get_current_blog_id() ) . \'user_roles\';
// copy current roles
self::$default_roles = get_option( self::$role_key );
// convert roles
$my_tool->convert_roles();
}
/**
* Reset changes made to roles
*/
private static function reset_roles() {
update_option( self::$role_key, self::$default_roles );
// refresh loaded roles
self::flush_roles();
}
/**
* From WordPress core\'s user/capabilities.php tests
*/
private static function flush_roles() {
// we want to make sure we\'re testing against the db, not just in-memory data
// this will flush everything and reload it from the db
unset( $GLOBALS[\'wp_user_roles\'] );
global $wp_roles;
$wp_roles = new WP_Roles();
}
类中的静态变量可以定义如下:
protected static $role_key;
protected static $default_roles;
现在,我的测试通过了,不管它们被称为什么顺序。