From 9ee17a79210e9010fb774c841de559c2cf26d2fe Mon Sep 17 00:00:00 2001 From: Anton Vlasenko <43744263+anton-vlasenko@users.noreply.github.com> Date: Mon, 16 Jan 2023 13:49:44 +0100 Subject: [PATCH] Run PHPUnit jobs across multiple PHP versions (#46510) 1. Run PHPUnit tests on all PHP versions (5.6 through 8.2) using the CI jobs. 2. Shows code style errors on the "Files changed" tab (same as Core); 3. Fix an issue with wp-env as it used non-optimal PHPUnit versions on PHP 7.3 and 7.4; Props @jrfnl , @dmsnell , @anton-vlasenko --- .cache/.gitkeep | 0 .github/workflows/unit-test.yml | 162 ++++++++++++++++-- .gitignore | 7 + packages/env/CHANGELOG.md | 6 + .../env/lib/build-docker-compose-config.js | 6 +- phpcs.xml.dist | 3 + phpunit/block-supports/layout-test.php | 15 ++ ...ock-pattern-categories-controller-test.php | 27 ++- phpunit/class-wp-theme-json-resolver-test.php | 15 ++ phpunit/wp-theme-json-test.php | 14 ++ 10 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 .cache/.gitkeep diff --git a/.cache/.gitkeep b/.cache/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c1fd9850191da..4a5d1f89bb33e 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -9,6 +9,8 @@ on: - trunk - 'release/**' - 'wp/**' + # Allow manually triggering the workflow. + workflow_dispatch: # Cancels all previous workflow runs for pull requests that have not completed. concurrency: @@ -51,39 +53,179 @@ jobs: - name: Running the date tests run: npm run test:unit:date -- --ci --maxWorkers=2 --cacheDirectory="$HOME/.jest-cache" - unit-php: - name: PHP + test-php: + name: PHP ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }} on ubuntu-latest runs-on: ubuntu-latest + timeout-minutes: 20 if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} + strategy: + fail-fast: true + matrix: + php: + - '5.6' + - '7.0' + - '7.1' + - '7.2' + - '7.3' + - '7.4' + - '8.0' + - '8.1' + - '8.2' + multisite: [false, true] + + env: + WP_ENV_PHP_VERSION: ${{ matrix.php }} steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 - - name: Use desired version of NodeJS + - name: Set up Node.js uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3.5.1 with: node-version-file: '.nvmrc' cache: npm - - name: Npm install and build + ## + # This allows Composer dependencies to be installed using a single step. + # + # Since the tests are currently run within the Docker containers where the PHP version varies, + # the same PHP version needs to be configured for the action runner machine so that the correct + # dependency versions are installed and cached. + ## + - name: Set up PHP + uses: shivammathur/setup-php@1a18b2267f80291a81ca1d33e7c851fe09e7dfc4 # v2.22.0 + with: + php-version: '${{ matrix.php }}' + ini-file: development + coverage: none + + # Ensure that Composer installs the correct versions of packages. + - name: Override PHP version in composer.json + run: composer config platform.php ${{ matrix.php }} + + # The spatie/phpunit-watcher package is not compatible with PHP < 7.2. + # It must be removed before running the tests. + - name: Remove incompatible Composer packages + if: ${{ matrix.php < '7.2' }} + run: composer remove spatie/phpunit-watcher --dev --no-update + + # Since Composer dependencies are installed using `composer update` and no lock file is in version control, + # passing a custom cache suffix ensures that the cache is flushed at least once per week. + - name: Install Composer dependencies + uses: ramsey/composer-install@83af392bf5f031813d25e6fe4cd626cdba9a2df6 # v2.2.0 + with: + custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") + + - name: Install npm dependencies run: | npm ci npm run build - - name: Install WordPress + - name: Docker debug information run: | - npm run wp-env start + docker -v + docker-compose -v - - name: Running lint check - run: npm run lint:php + - name: General debug information + run: | + npm --version + node --version + curl --version + git --version + svn --version + locale -a + + - name: Start Docker environment + run: npm run wp-env start + + - name: Log running Docker containers + run: docker ps -a + + - name: Docker container debug information + run: | + npm run wp-env run tests-mysql "mysql --version" + npm run wp-env run tests-wordpress "php --version" + npm run wp-env run tests-wordpress "php -m" + npm run wp-env run tests-wordpress "php -i" + npm run wp-env run tests-wordpress "/var/www/html/wp-content/plugins/gutenberg/vendor/bin/phpunit --version" + npm run wp-env run tests-wordpress "locale -a" - name: Running single site unit tests + if: ${{ ! matrix.multisite }} run: npm run test:unit:php - if: ${{ success() || failure() }} - name: Running multisite unit tests + if: ${{ matrix.multisite }} run: npm run test:unit:php:multisite - if: ${{ success() || failure() }} + + phpcs: + name: PHP coding standards + runs-on: ubuntu-latest + timeout-minutes: 20 + if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} + + steps: + - name: Checkout repository + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + + - name: Set up PHP + uses: shivammathur/setup-php@1a18b2267f80291a81ca1d33e7c851fe09e7dfc4 # v2.22.0 + with: + php-version: '7.4' + coverage: none + tools: cs2pr + + # This date is used to ensure that the PHPCS cache is cleared at least once every week. + # http://man7.org/linux/man-pages/man1/date.1.html + - name: "Get last Monday's date" + id: get-date + run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT + + - name: Cache PHPCS scan cache + uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 # v3.0.11 + with: + path: .cache/phpcs.json + key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} + + # Since Composer dependencies are installed using `composer update` and no lock file is in version control, + # passing a custom cache suffix ensures that the cache is flushed at least once per week. + - name: Install Composer dependencies + uses: ramsey/composer-install@83af392bf5f031813d25e6fe4cd626cdba9a2df6 # v2.2.0 + with: + custom-cache-suffix: ${{ steps.get-date.outputs.date }} + + - name: Make Composer packages available globally + run: echo "${PWD}/vendor/bin" >> $GITHUB_PATH + + - name: Run PHPCS on all Gutenberg files + id: phpcs-gutenberg + run: phpcs --report-full --report-checkstyle=./.cache/phpcs-report.xml + + - name: Show PHPCS results in PR + if: ${{ always() && steps.phpcs-gutenberg.outcome == 'failure' }} + run: cs2pr ./.cache/phpcs-report.xml + + - name: Ensure version-controlled files are not modified during the tests + run: git diff --exit-code + + # This job is deprecated but be present for compatibility reasons. + unit-php: + name: PHP + runs-on: ubuntu-latest + needs: [test-php, phpcs] + if: ${{ always() }} + steps: + - name: Fail the job if the PHPUnit tests fail + if: ${{ needs.test-php.result != 'success' }} + run: exit 1 + + - name: "Fail the job if the code doesn't conform to the coding standards" + if: ${{ needs.phpcs.result != 'success' }} + run: exit 1 + + - name: Mark the job as passed if all the checks pass + if: ${{ needs.test-php.result == 'success' && needs.phpcs.result == 'success' }} + run: exit 0 mobile-unit-js: name: Mobile diff --git a/.gitignore b/.gitignore index aebfcd623ad2f..71ffc1c5bbb25 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,14 @@ yarn.lock /perf-envs /composer.lock +# The /.cache folder is needed for phpcs to cache results between runs, while other .cache folders must be ignored +# It is not possible to re-include a file if a parent directory of that file is excluded +# So, both /.cache and /.cache./.gitkeep must be re-included .cache +!/.cache/ +/.cache/** +!/.cache/.gitkeep + .eslintcache *.tsbuildinfo diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 8bf26e02df19f..e8e0c0e1b5407 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +### Bug fix +- PHP 7.3 and 7.4 must use PHPUnit 9. + +### Enhancement +- It's now possible to run PHPUnit tests on PHP 8.1 and 8.2. + ## 5.9.0 (2023-01-02) ## 5.8.0 (2022-12-14) diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index ff85ba807f00a..7b27f85a7f6cf 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -181,9 +181,11 @@ module.exports = function buildDockerComposeConfig( config ) { phpunitTag = '6' + phpunitPhpVersion; } else if ( testsPhpVersion === '7.1' ) { phpunitTag = '7' + phpunitPhpVersion; - } else if ( [ '7.2', '7.3', '7.4' ].indexOf( testsPhpVersion ) >= 0 ) { + } else if ( testsPhpVersion === '7.2' ) { phpunitTag = '8' + phpunitPhpVersion; - } else if ( testsPhpVersion === '8.0' ) { + } else if ( + [ '7.3', '7.4', '8.0', '8.1', '8.2' ].indexOf( testsPhpVersion ) >= 0 + ) { phpunitTag = '9' + phpunitPhpVersion; } const phpunitImage = `wordpressdevelop/phpunit:${ phpunitTag }`; diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 7473a44d819bc..e48167d470ee8 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -32,6 +32,9 @@ + + + ./bin ./gutenberg.php ./lib diff --git a/phpunit/block-supports/layout-test.php b/phpunit/block-supports/layout-test.php index a22d77cf35408..9a01a371f72de 100644 --- a/phpunit/block-supports/layout-test.php +++ b/phpunit/block-supports/layout-test.php @@ -7,6 +7,21 @@ */ class WP_Block_Supports_Layout_Test extends WP_UnitTestCase { + /** + * @var string|null + */ + private $theme_root; + + /** + * @var array|null + */ + private $orig_theme_dir; + + /** + * @var array|null + */ + private $queries; + public function set_up() { parent::set_up(); $this->theme_root = realpath( __DIR__ . '/../data/themedir1' ); diff --git a/phpunit/class-wp-rest-block-pattern-categories-controller-test.php b/phpunit/class-wp-rest-block-pattern-categories-controller-test.php index beadbfc75d073..bdbaa819ba3f8 100644 --- a/phpunit/class-wp-rest-block-pattern-categories-controller-test.php +++ b/phpunit/class-wp-rest-block-pattern-categories-controller-test.php @@ -14,7 +14,7 @@ */ class WP_REST_Block_Pattern_Categories_Controller_Test extends WP_Test_REST_Controller_Testcase { protected static $admin_id; - protected static $orig_registry; + protected static $original_instance_value; public function set_up() { parent::set_up(); @@ -26,11 +26,13 @@ public static function wpSetupBeforeClass( $factory ) { self::$admin_id = $factory->user->create( array( 'role' => 'administrator' ) ); // Setup an empty testing instance of `WP_Block_Pattern_Categories_Registry` and save the original. - $reflection = new ReflectionClass( 'WP_Block_Pattern_Categories_Registry' ); - $reflection->getProperty( 'instance' )->setAccessible( true ); - self::$orig_registry = $reflection->getStaticPropertyValue( 'instance' ); - $test_registry = new WP_Block_Pattern_Categories_Registry(); - $reflection->setStaticPropertyValue( 'instance', $test_registry ); + $reflection = new ReflectionClass( 'WP_Block_Pattern_Categories_Registry' ); + $instance_property = $reflection->getProperty( 'instance' ); + $instance_property->setAccessible( true ); + self::$original_instance_value = $instance_property->getValue( null ); + + $test_registry = new WP_Block_Pattern_Categories_Registry(); + $instance_property->setValue( $test_registry ); // Register some categories in the test registry. $test_registry->register( 'test', array( 'label' => 'Test' ) ); @@ -42,8 +44,11 @@ public static function wpTearDownAfterClass() { self::delete_user( self::$admin_id ); // Restore the original registry instance. - $reflection = new ReflectionClass( 'WP_Block_Pattern_Categories_Registry' ); - $reflection->setStaticPropertyValue( 'instance', self::$orig_registry ); + $reflection = new ReflectionClass( 'WP_Block_Pattern_Categories_Registry' ); + $instance_property = $reflection->getProperty( 'instance' ); + $instance_property->setAccessible( true ); + $instance_property->setValue( self::$original_instance_value ); + $instance_property->setAccessible( false ); } public function test_register_routes() { @@ -79,21 +84,27 @@ public function test_get_items() { public function test_context_param() { $this->markTestIncomplete(); } + public function test_get_item() { $this->markTestIncomplete(); } + public function test_create_item() { $this->markTestIncomplete(); } + public function test_update_item() { $this->markTestIncomplete(); } + public function test_delete_item() { $this->markTestIncomplete(); } + public function test_prepare_item() { $this->markTestIncomplete(); } + public function test_get_item_schema() { $this->markTestIncomplete(); } diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index f872b251a7784..7b46dc3cd0d4a 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -43,6 +43,21 @@ class WP_Theme_JSON_Resolver_Gutenberg_Test extends WP_UnitTestCase { */ private static $property_core_orig_value; + /** + * @var string|null + */ + private $theme_root; + + /** + * @var array|null + */ + private $orig_theme_dir; + + /** + * @var array|null + */ + private $queries; + public static function set_up_before_class() { parent::set_up_before_class(); diff --git a/phpunit/wp-theme-json-test.php b/phpunit/wp-theme-json-test.php index 0d92d33faf88d..96fd1ec82c5f1 100644 --- a/phpunit/wp-theme-json-test.php +++ b/phpunit/wp-theme-json-test.php @@ -6,6 +6,20 @@ */ class WP_Theme_Json_Test extends WP_UnitTestCase { + /** + * @var string|null + */ + private $theme_root; + + /** + * @var array|null + */ + private $orig_theme_dir; + + /** + * @var array|null + */ + private $queries; public function set_up() { parent::set_up();