-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Test Coverage for Web Worker Offloading Plugin #1871
base: trunk
Are you sure you want to change the base?
Improve Test Coverage for Web Worker Offloading Plugin #1871
Conversation
…ge in web-worker-offloading plugin
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## trunk #1871 +/- ##
==========================================
+ Coverage 65.89% 68.01% +2.12%
==========================================
Files 88 86 -2
Lines 6878 6985 +107
==========================================
+ Hits 4532 4751 +219
+ Misses 2346 2234 -112
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
/** | ||
* Test the function that loads third party plugin integrations. | ||
* | ||
* @covers ::plwwo_load_third_party_integrations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @covers ::plwwo_load_third_party_integrations | |
* @covers ::plwwo_load_third_party_integrations | |
* @runInSeparateProcess |
Since a constant is not removed after a test completes, it's important to run in a separate process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When trying to run is a separate process, I'm getting error as Serialization of 'Closure' is not allowed
, and I'm not sure how to resolve this.
Attaching error log below :
Runtime: PHP 8.2.27 with Xdebug 3.4.1
Configuration: /var/www/html/wp-content/plugins/performance/phpunit.xml.dist
..................<script id="web-worker-offloading-js-before">
window.partytown = {...(window.partytown || {}), ...{"lib":"\/wp-content\/plugins\/performance\/plugins\/web-worker-offloading\/build\/"}};
</script>
<script id="web-worker-offloading-js-after">
const t={preserveBehavior:!1},e=e=>{if("string"==typeof e)return[e,t];const[n,r=t]=e;return[n,{...t,...r}]},n=Object.freeze((t=>{const e=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((t=>{"function"==typeof n[t]&&e.add(t)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(e)})());!function(t,r,o,i,a,s,c,d,l,p,u=t,f){function h(){f||(f=1,"/"==(c=(s.lib||"/~partytown/")+(s.debug?"debug/":""))[0]&&(l=r.querySelectorAll('script[type="text/partytown"]'),i!=t?i.dispatchEvent(new CustomEvent("pt1",{detail:t})):(d=setTimeout(v,1e4),r.addEventListener("pt0",w),a?y(1):o.serviceWorker?o.serviceWorker.register(c+(s.swPath||"partytown-sw.js"),{scope:c}).then((function(t){t.active?y():t.installing&&t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&y()}))}),console.error):v())))}function y(e){p=r.createElement(e?"script":"iframe"),t._pttab=Date.now(),e||(p.style.display="block",p.style.width="0",p.style.height="0",p.style.border="0",p.style.visibility="hidden",p.setAttribute("aria-hidden",!0)),p.src=c+"partytown-"+(e?"atomics.js?v=0.10.2":"sandbox-sw.html?"+t._pttab),r.querySelector(s.sandboxParent||"body").appendChild(p)}function v(n,o){for(w(),i==t&&(s.forward||[]).map((function(n){const[r]=e(n);delete t[r.split(".")[0]]})),n=0;n<l.length;n++)(o=r.createElement("script")).innerHTML=l[n].innerHTML,o.nonce=s.nonce,r.head.appendChild(o);p&&p.parentNode.removeChild(p)}function w(){clearTimeout(d)}s=t.partytown||{},i==t&&(s.forward||[]).map((function(r){const[o,{preserveBehavior:i}]=e(r);u=t,o.split(".").map((function(e,r,o){var a;u=u[o[r]]=r+1<o.length?u[o[r]]||(a=o[r+1],n.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:n,thisObject:r}=((t,e)=>{let n=t;for(let t=0;t<e.length-1;t+=1)n=n[e[t]];return{thisObject:n,methodOrProperty:e.length>0?n[e[e.length-1]]:void 0}})(t,o);"function"==typeof n&&(e=(...t)=>n.apply(r,...t))}return function(){let n;return e&&(n=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),n}})()}))})),"complete"==r.readyState?h():(t.addEventListener("DOMContentLoaded",h),t.addEventListener("load",h))}(window,document,navigator,top,window.crossOriginIsolated);
</script>
<script type="text/partytown" src="https://example.com/test-script.js?ver=1.0.0" id="test-script-js"></script>
Serialization of 'Closure' is not allowed
Script WP_MULTISITE=1 phpunit --exclude-group=ms-excluded handling the test-multisite event returned with error code 2
Script @test-multisite --verbose --testsuite web-worker-offloading was called via test-multisite:web-worker-offloading
✖ Command failed with exit code 2
Command failed with exit code 2
cc : @westonruter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I typically see that when @runInSeparateProcess
is added for a test that has a closure among the data in the data provider. But this test has no data provider, so I'm confused why it is occuring for this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhkk, so should I keep it as is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to various things to get it to work to run in a separate process but it was too messy. There are closures defined in some global variable in WordPress core, so I tried to remove them during the tests, but I still had trouble. We'll just not test that now I guess.
Patch
commit b1af2d50c95cee24c554b224d0fb06c7f61a34f2
Merge: 10002da03 a287b432a
Author: Weston Ruter <[email protected]>
Date: Fri Feb 21 13:58:58 2025 +0800
WIP on add/code_coverage_web_worker: 10002da03 fixup! Fix printing of output during test
diff --cc plugins/web-worker-offloading/tests/test-web-worker-offloading-load-third-party-integrations.php
index 000000000,3d6d7e2b7..d3491eea8
mode 000000,100644..100644
--- a/plugins/web-worker-offloading/tests/test-web-worker-offloading-load-third-party-integrations.php
+++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading-load-third-party-integrations.php
@@@ -1,0 -1,66 +1,67 @@@
+ <?php
+ /**
+ * Test cases for Web Worker Offloading: Load Third Party Integrations
+ *
+ * @package web-worker-offloading
+ * @runInSeparateProcess
+ */
+
+ class Test_Web_Worker_Offloading_Load_Third_Party_Integrations extends WP_UnitTestCase {
+
+ /**
+ * Original $_wp_registered_theme_features global.
+ *
+ * @var array
+ */
- static private $original_wp_registered_theme_features;
++ private static $original_wp_registered_theme_features;
+
+ /**
+ * Runs the routine before setting up all tests.
+ */
+ public static function set_up_before_class(): void {
+ parent::set_up_before_class();
+ self::$original_wp_registered_theme_features = $GLOBALS['_wp_registered_theme_features'];
+
+ // Empty global which contains a closure since it cannot be serialized to run in a separate process.
+ $GLOBALS['_wp_registered_theme_features'] = array();
+ }
+
+ /**
+ * Runs the routine after all tests have been run.
+ */
+ public static function tear_down_after_class(): void {
+ parent::tear_down_after_class();
+ $GLOBALS['_wp_registered_theme_features'] = self::$original_wp_registered_theme_features;
+ }
+
+ /**
- * Test the function doesn't third party plugin integrations when none are active.
++ * Test the function that loads third party plugin integrations.
+ *
+ * @covers ::plwwo_load_third_party_integrations
++ *
++ * @runInSeparateProcess
+ */
- public function test_plwwo_load_third_party_integrations_when_none_active(): void {
++ public function test_plwwo_load_third_party_integrations_when_sitekit_active(): void {
++ if ( ! defined( 'GOOGLESITEKIT_VERSION' ) ) {
++ define( 'GOOGLESITEKIT_VERSION', '1.0.0' );
++ }
+ do_action( 'plugins_loaded' );
+
- // Check that the integrations have been loaded.
- $this->assertFalse( function_exists( 'plwwo_google_site_kit_configure' ) );
++ $this->assertTrue( function_exists( 'plwwo_google_site_kit_configure' ) );
+ $this->assertFalse( function_exists( 'plwwo_rank_math_configure' ) );
+ $this->assertFalse( function_exists( 'plwwo_woocommerce_configure' ) );
+ }
+
+ /**
- * Test the function that loads third party plugin integrations.
++ * Test the function doesn't third party plugin integrations when none are active.
+ *
+ * @covers ::plwwo_load_third_party_integrations
+ */
- public function test_plwwo_load_third_party_integrations_when_sitekit_active(): void {
- if ( ! defined( 'GOOGLESITEKIT_VERSION' ) ) {
- define( 'GOOGLESITEKIT_VERSION', '1.0.0' );
- }
++ public function test_plwwo_load_third_party_integrations_when_none_active(): void {
+ do_action( 'plugins_loaded' );
+
- $this->assertTrue( function_exists( 'plwwo_google_site_kit_configure' ) );
++ $this->assertFalse( function_exists( 'plwwo_google_site_kit_configure' ) );
+ $this->assertFalse( function_exists( 'plwwo_rank_math_configure' ) );
+ $this->assertFalse( function_exists( 'plwwo_woocommerce_configure' ) );
+ }
+ }
diff --cc tools/phpunit/bootstrap.php
index b845c92fd,b845c92fd..2be1db391
--- a/tools/phpunit/bootstrap.php
+++ b/tools/phpunit/bootstrap.php
@@@ -42,30 -42,30 +42,31 @@@ if ( false !== strpos( $_test_root, 'wp
require_once $_test_root . '/includes/functions.php';
// Check if we use the plugin's test suite. If so, disable the PL plugin and only load the requested plugin.
--$plugin_name = '';
++global $test_plugin_name;
++$test_plugin_name = '';
foreach ( $_SERVER['argv'] as $index => $arg ) {
if (
'--testsuite' === $arg &&
isset( $_SERVER['argv'][ $index + 1 ] ) &&
file_exists( TESTS_REPO_ROOT_DIR . '/plugins/' . $_SERVER['argv'][ $index + 1 ] )
) {
-- $plugin_name = $_SERVER['argv'][ $index + 1 ];
++ $test_plugin_name = $_SERVER['argv'][ $index + 1 ];
}
}
// Set default plugin to load if not specified.
--if ( '' === $plugin_name ) {
-- $plugin_name = 'performance-lab';
++if ( '' === $test_plugin_name ) {
++ $test_plugin_name = 'performance-lab';
}
--define( 'TESTS_PLUGIN_DIR', TESTS_REPO_ROOT_DIR . "/plugins/$plugin_name" );
++define( 'TESTS_PLUGIN_DIR', TESTS_REPO_ROOT_DIR . "/plugins/$test_plugin_name" );
/**
* Load plugin bootstrap and any dependencies.
*
* @param string $plugin_name Plugin slug to load.
*/
--$load_plugin = static function ( string $plugin_name ) use ( &$load_plugin ): void {
++function test_load_plugin( string $plugin_name ): void {
$plugin_test_path = TESTS_REPO_ROOT_DIR . '/plugins/' . $plugin_name;
if ( file_exists( $plugin_test_path . '/' . $plugin_name . '.php' ) ) {
$plugin_file = $plugin_test_path . '/' . $plugin_name . '.php';
@@@ -78,7 -78,7 +79,7 @@@
if ( 1 === preg_match( '/^ \* Requires Plugins:\s*(.+)$/m', (string) file_get_contents( $plugin_file ), $matches ) ) {
foreach ( (array) preg_split( '/\s*,\s*/', $matches[1] ) as $requires_plugin ) {
-- $load_plugin( (string) $requires_plugin );
++ test_load_plugin( (string) $requires_plugin );
}
}
@@@ -91,42 -91,42 +92,49 @@@
require_once $plugin_file;
};
++function test_load_plugin_at_plugins_loaded(): void {
++ global $test_plugin_name;
++ test_load_plugin( $test_plugin_name );
++}
++
tests_add_filter(
'plugins_loaded',
-- static function () use ( $load_plugin, $plugin_name ): void {
-- $load_plugin( $plugin_name );
-- },
++ 'test_load_plugin_at_plugins_loaded',
1
);
--if ( 'performance-lab' === $plugin_name ) {
++function test_require_performance_lab_includes(): void {
++ require_once TESTS_REPO_ROOT_DIR . '/plugins/performance-lab/includes/admin/load.php';
++ require_once TESTS_REPO_ROOT_DIR . '/plugins/performance-lab/includes/admin/server-timing.php';
++ require_once TESTS_REPO_ROOT_DIR . '/plugins/performance-lab/includes/admin/plugins.php';
++}
++
++if ( 'performance-lab' === $test_plugin_name ) {
// Add filter to ensure the plugin's admin integration is loaded for tests.
tests_add_filter(
'plugins_loaded',
-- static function () use ( $plugin_name ): void {
-- require_once TESTS_REPO_ROOT_DIR . '/plugins/' . $plugin_name . '/includes/admin/load.php';
-- require_once TESTS_REPO_ROOT_DIR . '/plugins/' . $plugin_name . '/includes/admin/server-timing.php';
-- require_once TESTS_REPO_ROOT_DIR . '/plugins/' . $plugin_name . '/includes/admin/plugins.php';
-- },
++ 'test_require_performance_lab_includes',
1
);
}
++function test_clean_up_object_cache_dropins( bool $passthrough ): bool {
++ $cleanup_files = array(
++ WP_CONTENT_DIR . '/object-cache.php',
++ WP_CONTENT_DIR . '/object-cache-plst-orig.php',
++ );
++ foreach ( $cleanup_files as $cleanup_file ) {
++ if ( file_exists( $cleanup_file ) ) {
++ unlink( $cleanup_file );
++ }
++ }
++ return $passthrough;
++}
++
// Clean up object-cache drop-ins after possible previous failed tests.
tests_add_filter(
'enable_loading_object_cache_dropin',
-- static function ( bool $passthrough ): bool {
-- $cleanup_files = array(
-- WP_CONTENT_DIR . '/object-cache.php',
-- WP_CONTENT_DIR . '/object-cache-plst-orig.php',
-- );
-- foreach ( $cleanup_files as $cleanup_file ) {
-- if ( file_exists( $cleanup_file ) ) {
-- unlink( $cleanup_file );
-- }
-- }
-- return $passthrough;
-- }
++ 'test_clean_up_object_cache_dropins'
);
// Start up the WP testing environment.
…rker-offloading plugin
…rker-offloading plugin
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @[email protected]. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Summary
This is part of #1789:
@covers
Annotationscc : @westonruter