Commit bc648b5c32c for woocommerce

commit bc648b5c32c61442ef1a6fd810e88a08d802d33f
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date:   Fri Jul 31 16:57:17 2026 +0300

    [tests] Fix unit tests that skip their parent setup or teardown (#67177)

    * fix: call the parent teardown from unit tests that override it

    Six unit test classes override tearDown() (or tearDownAfterClass()) without
    calling the parent. The parent is what reaches the WordPress test framework's
    tear_down(), which the PHPUnit Polyfills bridge invokes and which issues the
    ROLLBACK ending the per-test DB transaction, resets the query and post
    globals, and clears the current user.

    Skipping it means none of that runs. The next test's START TRANSACTION
    implicitly commits whatever the previous test left open, so rows created
    during a test outlive it: probing MarketingRecommendationsTest, which creates
    an administrator per test, showed 5 administrators across 4 tests against 2
    once the parent call is in place.

    Two of the classes were also missing parent::setUp(), so no transaction was
    started for them at all; both calls are added there.

    The parent call goes last, so each class's own cleanup still runs inside the
    transaction being rolled back.

    Not every case leaked. CheckoutFieldsFrontendTest extends the polyfill
    TestCase rather than a WordPress one, so nothing in its chain rolls anything
    back and the change is for symmetry with its setUp(). Reports_Orders_Stats
    overrides the static tearDownAfterClass() instead, where the parent runs
    _delete_all_data() and flushes the object cache.

    Refs #67154

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    * fix: call the parent setup from unit tests that override it

    Twenty-seven lifecycle overrides across twenty-five test classes did not
    call their parent implementation. On a WordPress test case, overriding
    camelCase `setUp` bypasses the entire `set_up()` chain, not just the
    immediate parent: the PHPUnit Polyfills bridge is what dispatches
    `set_up()`, so `WC_Unit_Test_Case`, `WP_HTTP_TestCase` and
    `WP_UnitTestCase_Base` are all skipped at once.

    The per-test transaction is the costly part. `set_up()` issues
    `SET autocommit = 0; START TRANSACTION`, and `wpdb::db_connect()` builds
    a fresh connection for every class, so a class that skips setup runs its
    whole lifetime at `autocommit = 1` — every write commits immediately and
    the `ROLLBACK` in `tear_down()` is a no-op. Several of these classes do
    call `parent::tearDown()`, rolling back a transaction they never opened.
    Leaked rows in most tables get swept by `_delete_all_data()` at class
    teardown, but that function never touches `wp_options`, so a leaked
    option is permanent for the life of the test database.

    Skipping setup also loses `$this->factory`, `_backup_hooks()`, the
    `$_GET`/`$_POST`/`$_REQUEST` reset and object-cache flush, the
    deprecation catcher, the `pre_http_request` blocker that keeps unit
    tests off the network, `CodeHacker::reset_hacks()`, the `LegacyProxy`
    reset, and — at class level — `WC_Install::create_terms()`, which is the
    only thing that restores WooCommerce's default terms after the previous
    class deleted them.

    `WC_CLI_Update_Command_Test` needed three coordinated edits rather than
    one: it called `parent::set_up()` from `mock_wp_cli()`, a helper invoked
    inside the test body. That opened a transaction mid-test with no matching
    rollback, which the next test's `START TRANSACTION` implicitly committed.
    Adding the call to `set_up()` without deleting that one would have run
    the parent twice per test and made the leak worse.

    Parent calls go first in setup hooks and last in teardown. In
    `setUpBeforeClass` this is load-bearing rather than stylistic: the parent
    reconnects `$wpdb`, and MySQL rolls back the discarded connection's
    uncommitted work, so any write the method makes must happen after the
    parent call.

    `AbstractProductFiltersTest` reaches `parent::setUp()` through
    `set_up_test_case()`, an extension point that lets subclasses control
    where the transaction starts relative to fixture creation. It gets a
    docblock note instead of a code change.

    Verified against a locked full-suite baseline. Test and assertion counts
    and the skipped set are unchanged; failures drop from five to four,
    reproduced across two runs. `test_db_update_note_to_thanks_note` passes
    in isolation but was failing in the full suite purely on cross-class
    state that the missing setup let through.

    ---------

    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/fix-test-teardown-missing-parent-call b/plugins/woocommerce/changelog/fix-test-teardown-missing-parent-call
new file mode 100644
index 00000000000..359f20b67c6
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-test-teardown-missing-parent-call
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Call the parent setup and teardown from unit test classes that override them, so the per-test database transaction is opened and rolled back and test data no longer leaks between tests.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/notes/class-wc-tests-notes-run-db-update.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/notes/class-wc-tests-notes-run-db-update.php
index bf1d0d2eccc..f7b55a83e0d 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/admin/notes/class-wc-tests-notes-run-db-update.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/notes/class-wc-tests-notes-run-db-update.php
@@ -17,6 +17,8 @@ class WC_Tests_Notes_Run_Db_Update extends WC_Unit_Test_Case {
 	 *
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/wc-admin-functions.php';
 		include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/notes/class-wc-notes-run-db-update.php';

@@ -26,6 +28,8 @@ class WC_Tests_Notes_Run_Db_Update extends WC_Unit_Test_Case {
 	 * Clean up before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		if ( ! WC()->is_wc_admin_active() ) {
 			$this->markTestSkipped( 'WC Admin is not active on WP versions < 5.3' );
 			return;
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php
index 4be81320b2f..13fc6861834 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php
@@ -18,6 +18,8 @@ class WC_Tests_Admin_Report extends WC_Unit_Test_Case {
 	 *
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-admin-report.php';
 	}

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
index 5e748618177..b871119e446 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
@@ -16,6 +16,8 @@ class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
 	 * Load the necessary files, as they're not automatically loaded by WooCommerce.
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-admin-report.php';
 		include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-report-sales-by-date.php';
 	}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php b/plugins/woocommerce/tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php
index d0714c7cb85..aa559eee92b 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php
@@ -38,6 +38,8 @@ class WC_Tests_Customer_Download extends WC_Unit_Test_Case {
 	 * Tests set up.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->customer_id    = 1;
 		$this->customer_email = 'test@example.com';

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/util/notice-functions.php b/plugins/woocommerce/tests/legacy/unit-tests/util/notice-functions.php
index 6c78d1a3894..81aea38a787 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/util/notice-functions.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/util/notice-functions.php
@@ -18,6 +18,8 @@ class WC_Tests_Notice_Functions extends WC_Unit_Test_Case {
 	public function tearDown(): void {

 		WC()->session->set( 'wc_notices', null );
+
+		parent::tearDown();
 	}

 	/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-interval.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-interval.php
index eb7f3359ca1..f5ece349b8d 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-interval.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-interval.php
@@ -24,6 +24,8 @@ class WC_Admin_Tests_Reports_Interval_Stats extends WC_Unit_Test_Case {
 	 * Set current local timezone.
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		self::$local_tz = new DateTimeZone( wc_timezone_string() );
 	}

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
index ba2bca4b7cf..8c838e08890 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
@@ -17,6 +17,8 @@ class WC_Admin_Tests_RemoteSpecs_RuleProcessors_IsWooExpressRuleProcessor extend
 	 * Set Up Before Class.
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		/**
 		 * Fake function wc_calypso_bridge_is_woo_express_plan so that we can test the processor.
 		 */
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
index f67cb20f4c0..5a1d4b063f9 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
@@ -23,6 +23,11 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
 	 * Don't cache report data during these tests.
 	 */
 	public static function setUpBeforeClass(): void {
+		// Must come first: the parent reconnects `$wpdb`, which discards anything this
+		// method has written but not committed. The matching `parent::tearDownAfterClass()`
+		// goes last, so the two are deliberately not symmetrical.
+		parent::setUpBeforeClass();
+
 		add_filter( 'woocommerce_analytics_report_should_use_cache', '__return_false' );

 		$db_version = strstr( WC()->version, '-', true );
@@ -37,6 +42,8 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
 	 */
 	public static function tearDownAfterClass(): void {
 		remove_filter( 'woocommerce_analytics_report_should_use_cache', '__return_false' );
+
+		parent::tearDownAfterClass();
 	}

 	/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
index 2b7723528a8..1b1b28056fd 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
@@ -17,6 +17,8 @@ class WC_Admin_Tests_WCAdminAssets extends WP_UnitTestCase {
 	 * Setup
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		add_filter( 'woocommerce_admin_features', array( $this, 'turn_on_unminified_js_feature' ), 20, 1 );
 	}

@@ -25,6 +27,8 @@ class WC_Admin_Tests_WCAdminAssets extends WP_UnitTestCase {
 	 */
 	public function tearDown(): void {
 		remove_filter( 'woocommerce_admin_features', array( $this, 'turn_on_unminified_js_feature' ), 20 );
+
+		parent::tearDown();
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/includes/cli/class-wc-cli-update-command-test.php b/plugins/woocommerce/tests/php/includes/cli/class-wc-cli-update-command-test.php
index e3a27bd7def..6337eed2d4f 100644
--- a/plugins/woocommerce/tests/php/includes/cli/class-wc-cli-update-command-test.php
+++ b/plugins/woocommerce/tests/php/includes/cli/class-wc-cli-update-command-test.php
@@ -26,6 +26,8 @@ class WC_CLI_Update_Command_Test extends WC_Unit_Test_Case {
 	 * Make WP_Install::$db_updates readable and capture the original value.
 	 */
 	public function set_up() {
+		parent::set_up();
+
 		$this->db_updates_property = new ReflectionProperty( WC_Install::class, 'db_updates' );
 		$this->db_updates_property->setAccessible( true );
 		$this->db_updates_original_value = $this->db_updates_property->getValue();
@@ -37,6 +39,8 @@ class WC_CLI_Update_Command_Test extends WC_Unit_Test_Case {
 	public function tear_down() {
 		$this->db_updates_property->setValue( $this->db_updates_original_value );
 		$this->db_updates_property->setAccessible( false );
+
+		parent::tear_down();
 	}

 	/**
@@ -86,8 +90,6 @@ class WC_CLI_Update_Command_Test extends WC_Unit_Test_Case {
 	 * Mock WP_CLI and related functionality.
 	 */
 	private function mock_wp_cli() {
-		parent::set_up();
-
 		$this->register_legacy_proxy_static_mocks(
 			array(
 				WP_CLI::class => array(
diff --git a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
index e9e86eed468..716c3e15585 100644
--- a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
+++ b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
@@ -10,6 +10,8 @@ class WC_REST_Terms_Controller_Tests extends WC_Unit_Test_Case {
 	 * Runs before any test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		// phpcs:disable Generic.CodeAnalysis, Squiz.Commenting
 		$this->sut = new class() extends WC_REST_Terms_Controller {
 			public function get_taxonomy( $request ) {
diff --git a/plugins/woocommerce/tests/php/src/Admin/API/MarketingRecommendationsTest.php b/plugins/woocommerce/tests/php/src/Admin/API/MarketingRecommendationsTest.php
index 144831eeba8..af1fd2da128 100644
--- a/plugins/woocommerce/tests/php/src/Admin/API/MarketingRecommendationsTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/API/MarketingRecommendationsTest.php
@@ -118,6 +118,8 @@ class MarketingRecommendationsTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function tearDown(): void {
 		remove_filter( 'pre_http_request', $this->response_mock_ref );
+
+		parent::tearDown();
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/src/Admin/Marketing/MarketingChannelsTest.php b/plugins/woocommerce/tests/php/src/Admin/Marketing/MarketingChannelsTest.php
index fdc112ae370..296df302f6a 100644
--- a/plugins/woocommerce/tests/php/src/Admin/Marketing/MarketingChannelsTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/Marketing/MarketingChannelsTest.php
@@ -15,6 +15,8 @@ class MarketingChannelsTest extends WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		remove_all_filters( 'woocommerce_marketing_channels' );
 	}

diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockHooksTests.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockHooksTests.php
index a26eb8ad52e..3f7167dd177 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockHooksTests.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockHooksTests.php
@@ -29,6 +29,8 @@ class BlockHooksTests extends WP_UnitTestCase {
 	 * Initiate the mock object.
 	 */
 	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
 		delete_option( self::$option_name );
 		self::$block_instance = new BlockHooksTestBlock();
 	}
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/Checkout.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/Checkout.php
index c7781c005d9..e2c1b7ce53e 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/Checkout.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/Checkout.php
@@ -44,6 +44,8 @@ class Checkout extends \WP_UnitTestCase {
 	 * @throws \Exception If the API class is not registered with container.
 	 */
 	protected function setUp(): void {
+		parent::setUp();
+
 		$this->asset_api            = Package::container()->get( API::class );
 		$this->registry             = new AssetDataRegistryMock( $this->asset_api );
 		$this->integration_registry = new IntegrationRegistry();
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductQuery.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductQuery.php
index f99eb24343c..b35fefa9bca 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductQuery.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductQuery.php
@@ -51,6 +51,8 @@ class ProductQuery extends \WP_UnitTestCase {
 	 * Initiate the mock object.
 	 */
 	protected function setUp(): void {
+		parent::setUp();
+
 		$this->block_instance = new ProductQueryMock();
 	}

diff --git a/plugins/woocommerce/tests/php/src/Blocks/Bootstrap/MainFile.php b/plugins/woocommerce/tests/php/src/Blocks/Bootstrap/MainFile.php
index 3572214b971..a0cd8d655e6 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Bootstrap/MainFile.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Bootstrap/MainFile.php
@@ -28,6 +28,8 @@ class MainFile extends WP_UnitTestCase {
 	 * Ensure that container is reset between tests.
 	 */
 	protected function setUp(): void {
+		parent::setUp();
+
 		// reset container.
 		$this->container = Package::container( true );
 	}
@@ -60,5 +62,7 @@ class MainFile extends WP_UnitTestCase {
 	 */
 	protected function tearDown(): void {
 		Package::init();
+
+		parent::tearDown();
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Domain/Services/CheckoutFieldsFrontendTest.php b/plugins/woocommerce/tests/php/src/Blocks/Domain/Services/CheckoutFieldsFrontendTest.php
index e4f2ad93611..2aeb6658b37 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Domain/Services/CheckoutFieldsFrontendTest.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Domain/Services/CheckoutFieldsFrontendTest.php
@@ -62,6 +62,8 @@ class CheckoutFieldsFrontendTest extends TestCase {
 			__internal_woocommerce_blocks_deregister_checkout_field( $field_id );
 		}
 		$this->registered_fields = [];
+
+		parent::tearDown();
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Helpers/TestValidateSchema.php b/plugins/woocommerce/tests/php/src/Blocks/Helpers/TestValidateSchema.php
index 6d0fa93cb25..a70030954d8 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Helpers/TestValidateSchema.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Helpers/TestValidateSchema.php
@@ -22,6 +22,8 @@ class TestValidateSchema extends \WP_UnitTestCase {
 	 * Setup schema.
 	 */
 	protected function setUp(): void {
+		parent::setUp();
+
 		$this->validate = new ValidateSchema(
 			[
 				'properties' => [
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Registry/Container.php b/plugins/woocommerce/tests/php/src/Blocks/Registry/Container.php
index f250f92ff98..00a0e8c34a2 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Registry/Container.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Registry/Container.php
@@ -19,6 +19,8 @@ class Container extends TestCase {
 	private $container;

 	protected function setUp(): void {
+		parent::setUp();
+
 		$this->container = new ContainerTest;
 	}

diff --git a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/ControllerTests.php b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/ControllerTests.php
index 9d18bc67791..f69b046c56d 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/ControllerTests.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/ControllerTests.php
@@ -13,6 +13,8 @@ class ControllerTests extends \WP_Test_REST_TestCase {
 	 * Setup Rest API server.
 	 */
 	protected function setUp(): void {
+		parent::setUp();
+
 		/** @var \WP_REST_Server $wp_rest_server */
 		global $wp_rest_server;
 		$wp_rest_server = new \Spy_REST_Server();
diff --git a/plugins/woocommerce/tests/php/src/Caching/CacheExceptionTest.php b/plugins/woocommerce/tests/php/src/Caching/CacheExceptionTest.php
index 8896b0f97fc..005a40a53d2 100644
--- a/plugins/woocommerce/tests/php/src/Caching/CacheExceptionTest.php
+++ b/plugins/woocommerce/tests/php/src/Caching/CacheExceptionTest.php
@@ -21,6 +21,8 @@ class CacheExceptionTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		// phpcs:disable Squiz.Commenting
 		$this->thrower = new class() extends ObjectCache {
 			public function get_object_type(): string {
diff --git a/plugins/woocommerce/tests/php/src/Caching/ObjectCacheTest.php b/plugins/woocommerce/tests/php/src/Caching/ObjectCacheTest.php
index 66c91c92c0c..b2bde1c0623 100644
--- a/plugins/woocommerce/tests/php/src/Caching/ObjectCacheTest.php
+++ b/plugins/woocommerce/tests/php/src/Caching/ObjectCacheTest.php
@@ -23,6 +23,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();

 		// phpcs:disable Squiz.Commenting

diff --git a/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/RuntimeContainerTest.php b/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/RuntimeContainerTest.php
index a4cd625624f..bfea987d5c1 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/RuntimeContainerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/RuntimeContainerTest.php
@@ -42,6 +42,8 @@ class RuntimeContainerTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->sut = new RuntimeContainer(
 			array( 'Foo\Bar' => $this )
 		);
diff --git a/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/TestingContainerTest.php b/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/TestingContainerTest.php
index 4d597391bf4..67c65aab9e5 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/TestingContainerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DependencyManagement/TestingContainerTest.php
@@ -28,6 +28,8 @@ class TestingContainerTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$base_container = new RuntimeContainer(
 			array( 'Foo\Bar' => $this )
 		);
diff --git a/plugins/woocommerce/tests/php/src/Internal/McStatsTest.php b/plugins/woocommerce/tests/php/src/Internal/McStatsTest.php
index 93c23f87920..055976746c0 100644
--- a/plugins/woocommerce/tests/php/src/Internal/McStatsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/McStatsTest.php
@@ -14,6 +14,8 @@ class McStatsTest extends \WC_Unit_Test_Case {
 	 * Set up. Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->sut = wc_get_container()->get( McStats::class );
 	}

diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductFilters/AbstractProductFiltersTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductFilters/AbstractProductFiltersTest.php
index 0a1075a66f8..f27825dd050 100644
--- a/plugins/woocommerce/tests/php/src/Internal/ProductFilters/AbstractProductFiltersTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/ProductFilters/AbstractProductFiltersTest.php
@@ -105,6 +105,9 @@ abstract class AbstractProductFiltersTest extends \WC_Unit_Test_Case {

 	/**
 	 * Runs before each test.
+	 *
+	 * `parent::setUp()` is reached through `set_up_test_case()`, which exists so subclasses
+	 * can control where the per-test transaction starts relative to fixture creation.
 	 */
 	public function setUp(): void {
 		$this->set_up_test_case();
diff --git a/plugins/woocommerce/tests/php/src/Proxies/ClassThatDependsOnLegacyCodeTest.php b/plugins/woocommerce/tests/php/src/Proxies/ClassThatDependsOnLegacyCodeTest.php
index cbdf20ce3aa..0b13b574b80 100644
--- a/plugins/woocommerce/tests/php/src/Proxies/ClassThatDependsOnLegacyCodeTest.php
+++ b/plugins/woocommerce/tests/php/src/Proxies/ClassThatDependsOnLegacyCodeTest.php
@@ -24,6 +24,8 @@ class ClassThatDependsOnLegacyCodeTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$container = wc_get_container();

 		$this->sut = $container->get( ClassThatDependsOnLegacyCode::class );
diff --git a/plugins/woocommerce/tests/php/src/Proxies/DynamicDecoratorTest.php b/plugins/woocommerce/tests/php/src/Proxies/DynamicDecoratorTest.php
index 414df6d95f7..5c203661131 100644
--- a/plugins/woocommerce/tests/php/src/Proxies/DynamicDecoratorTest.php
+++ b/plugins/woocommerce/tests/php/src/Proxies/DynamicDecoratorTest.php
@@ -23,6 +23,8 @@ class DynamicDecoratorTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->sut = new DynamicDecorator( new ClassWithReplaceableMembers() );
 	}

diff --git a/plugins/woocommerce/tests/php/src/Proxies/LegacyProxyTest.php b/plugins/woocommerce/tests/php/src/Proxies/LegacyProxyTest.php
index a6e5e2f7f72..5d74a6bbf63 100644
--- a/plugins/woocommerce/tests/php/src/Proxies/LegacyProxyTest.php
+++ b/plugins/woocommerce/tests/php/src/Proxies/LegacyProxyTest.php
@@ -25,6 +25,8 @@ class LegacyProxyTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->sut = new LegacyProxy();
 	}

diff --git a/plugins/woocommerce/tests/php/src/Proxies/MockableLegacyProxyTest.php b/plugins/woocommerce/tests/php/src/Proxies/MockableLegacyProxyTest.php
index ec0f2761a68..eb6a40f5a0b 100644
--- a/plugins/woocommerce/tests/php/src/Proxies/MockableLegacyProxyTest.php
+++ b/plugins/woocommerce/tests/php/src/Proxies/MockableLegacyProxyTest.php
@@ -24,6 +24,8 @@ class MockableLegacyProxyTest extends \WC_Unit_Test_Case {
 	 * Runs before each test.
 	 */
 	public function setUp(): void {
+		parent::setUp();
+
 		$this->sut = new MockableLegacyProxy();
 	}