diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php index 3a5d52b0706a9..7e27e496d0123 100644 --- a/tests/phpunit/includes/abstract-testcase.php +++ b/tests/phpunit/includes/abstract-testcase.php @@ -108,6 +108,8 @@ public function set_up() { set_time_limit( 0 ); + $this->skip_default_excluded_groups(); + $this->factory = static::factory(); if ( ! self::$ignore_files ) { @@ -143,6 +145,43 @@ public function set_up() { add_filter( 'wp_hash_password_options', array( $this, 'wp_hash_password_options' ), 1, 2 ); } + /** + * Skips tests that belong to groups excluded by default unless those groups were explicitly requested. + */ + protected function skip_default_excluded_groups() { + $skipped_groups = self::get_default_excluded_groups_for_test( $this->getGroups() ); + + if ( $skipped_groups ) { + $this->markTestSkipped( + sprintf( + 'This test belongs to a group that is skipped by default: %s. Use --group %s to run it.', + implode( ', ', $skipped_groups ), + $skipped_groups[0] + ) + ); + } + } + + /** + * Returns the default-excluded groups that apply to a test and were not explicitly requested. + * + * @param string[] $groups Test groups. + * @return string[] Matching excluded groups. + */ + public static function get_default_excluded_groups_for_test( array $groups ) { + $default_excluded_groups = WP_PHPUnit_Util_Getopt::get_skipped_groups(); + + return array_values( + array_filter( + $groups, + static function ( $group ) use ( $default_excluded_groups ) { + return in_array( $group, $default_excluded_groups, true ) + && ! WP_PHPUnit_Util_Getopt::is_group_requested( $group ); + } + ) + ); + } + /** * Sets the bcrypt cost option for password hashing during tests. * diff --git a/tests/phpunit/includes/bootstrap.php b/tests/phpunit/includes/bootstrap.php index e308dcb5a6e1c..d54ed34ab64c4 100644 --- a/tests/phpunit/includes/bootstrap.php +++ b/tests/phpunit/includes/bootstrap.php @@ -345,42 +345,83 @@ function wp_tests_options( $value ) { * how you call phpunit has no effect. */ class WP_PHPUnit_Util_Getopt { - - public function __construct( $argv ) { + /** + * Groups that are skipped by default for the current test run. + * + * @var array + */ + protected static $skipped_groups = array(); + + /** + * Groups that were explicitly requested via the command line. + * + * @var array + */ + protected static $requested_groups = array(); + + /** + * Initializes the default skipped groups for the current test mode. + * + * @return array The groups skipped by default. + */ + protected static function get_default_skipped_groups() { $skipped_groups = array( - 'ajax' => true, - 'ms-files' => true, - 'external-http' => true, + 'ajax' => true, + 'ms-files' => true, + 'external-http' => true, + 'html-api-html5lib-tests' => true, ); + if ( defined( 'WP_TESTS_MULTISITE' ) && WP_TESTS_MULTISITE ) { + $skipped_groups['ms-excluded'] = true; + $skipped_groups['oembed-headers'] = true; + } else { + $skipped_groups['ms-required'] = true; + } + + return $skipped_groups; + } + + /** + * Resets the parsed command line state. + */ + public static function reset() { + self::$skipped_groups = self::get_default_skipped_groups(); + self::$requested_groups = array(); + } + + public function __construct( $argv ) { + self::reset(); + while ( current( $argv ) ) { $option = current( $argv ); $value = next( $argv ); switch ( $option ) { case '--exclude-group': - foreach ( $skipped_groups as $group_name => $skipped ) { - $skipped_groups[ $group_name ] = false; - } + // PHPUnit replaces XML exclusions when this option is provided. + // Keep our default skipped groups active unless they are requested explicitly. continue 2; case '--group': $groups = explode( ',', $value ); foreach ( $groups as $group ) { + self::$requested_groups[ $group ] = true; + if ( is_numeric( $group ) || preg_match( '/^(UT|Plugin)\d+$/', $group ) ) { WP_UnitTestCase::forceTicket( $group ); } } - foreach ( $skipped_groups as $group_name => $skipped ) { + foreach ( self::$skipped_groups as $group_name => $skipped ) { if ( in_array( $group_name, $groups, true ) ) { - $skipped_groups[ $group_name ] = false; + self::$skipped_groups[ $group_name ] = false; } } continue 2; } } - $skipped_groups = array_filter( $skipped_groups ); + $skipped_groups = array_filter( self::$skipped_groups ); foreach ( $skipped_groups as $group_name => $skipped ) { echo sprintf( 'Not running %1$s tests. To execute these, use --group %1$s.', $group_name ) . PHP_EOL; } @@ -392,5 +433,24 @@ public function __construct( $argv ) { echo PHP_EOL; } } + + /** + * Returns the groups that are still skipped by default for this run. + * + * @return string[] + */ + public static function get_skipped_groups() { + return array_keys( array_filter( self::$skipped_groups ) ); + } + + /** + * Determines whether a group was explicitly requested via the command line. + * + * @param string $group Group name. + * @return bool Whether the group was explicitly requested. + */ + public static function is_group_requested( $group ) { + return isset( self::$requested_groups[ $group ] ); + } } new WP_PHPUnit_Util_Getopt( $_SERVER['argv'] ); diff --git a/tests/phpunit/tests/phpunit/groupFilters.php b/tests/phpunit/tests/phpunit/groupFilters.php new file mode 100644 index 0000000000000..f06137aa057e2 --- /dev/null +++ b/tests/phpunit/tests/phpunit/groupFilters.php @@ -0,0 +1,54 @@ +assertSame( + array( 'ajax', 'external-http' ), + WP_UnitTestCase_Base::get_default_excluded_groups_for_test( array( 'ajax', 'external-http', 'query' ) ) + ); + } + + public function test_requested_group_is_not_reported_as_default_excluded() { + ob_start(); + new WP_PHPUnit_Util_Getopt( + array( + 'phpunit', + '--group', + 'ajax', + ) + ); + ob_end_clean(); + + $this->assertSame( + array(), + WP_UnitTestCase_Base::get_default_excluded_groups_for_test( array( 'ajax' ) ) + ); + } + + public function test_exclude_group_does_not_clear_default_excluded_groups() { + ob_start(); + new WP_PHPUnit_Util_Getopt( + array( + 'phpunit', + '--exclude-group', + 'import', + ) + ); + ob_end_clean(); + + $multisite_excluded_group = is_multisite() ? 'ms-excluded' : 'ms-required'; + + $this->assertSame( + array( 'ajax', $multisite_excluded_group ), + WP_UnitTestCase_Base::get_default_excluded_groups_for_test( array( 'ajax', $multisite_excluded_group ) ) + ); + } +}