diff --git a/include/test/test.h b/include/test/test.h
index c3b251e2cd4..b81cab4d7a4 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -92,6 +92,7 @@ struct ut_arg {
  * @force_run: true to run tests marked with the UTF_MANUAL flag
  * @workers: Number of parallel workers, 0 if not sharding tests
  * @worker_id: ID of this worker (0 to workers-1)
+ * @old_bootstage_count: bootstage record count saved before each test
  * @old_bloblist: stores the old gd->bloblist pointer
  * @soft_fail: continue execution of the test even after it fails
  * @expect_str: Temporary string used to hold expected string value
@@ -128,6 +129,7 @@ struct unit_test_state {
 	bool force_run;
 	int workers;
 	int worker_id;
+	uint old_bootstage_count;
 	void *old_bloblist;
 	bool soft_fail;
 	char expect_str[1024];
diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
index ed18ff68825..6fb76196e16 100755
--- a/test/py/tests/test_fit.py
+++ b/test/py/tests/test_fit.py
@@ -140,6 +140,12 @@ class TestFitImage:
       - run code coverage to make sure we are testing all the code
     """
 
+    @pytest.fixture(autouse=True)
+    def save_bootstage(self, ubman):
+        """Save and restore bootstage around each test."""
+        with utils.preserve_bootstage(ubman):
+            yield
+
     def make_fname(self, ubman, leaf):
         """Make a temporary filename
 
diff --git a/test/py/utils.py b/test/py/utils.py
index 083a3feddc2..9097f158496 100644
--- a/test/py/utils.py
+++ b/test/py/utils.py
@@ -14,8 +14,26 @@ import signal
 import sys
 import time
 import re
+from contextlib import contextmanager
 import pytest
 
+@contextmanager
+def preserve_bootstage(ubman):
+    """Context manager to save and restore bootstage record count.
+
+    Some commands (e.g. bootm) add bootstage records with unique IDs. These
+    accumulate across tests in a pytest session and can fill the bootstage
+    table. Use this around tests that trigger such commands.
+
+    Args:
+        ubman (ConsoleBase): U-Boot console connection
+    """
+    ubman.run_command('bootstage save')
+    try:
+        yield
+    finally:
+        ubman.run_command('bootstage restore')
+
 def md5sum_data(data):
     """Calculate the MD5 hash of some data.
 
diff --git a/test/test-main.c b/test/test-main.c
index 5db35b59760..77223cfbcb7 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -7,6 +7,7 @@
 #define LOG_CATEGORY	LOGC_TEST
 
 #include <blk.h>
+#include <bootstage.h>
 #include <console.h>
 #include <cyclic.h>
 #include <dm.h>
@@ -560,6 +561,8 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
 		gd_set_bloblist(NULL);
 	}
 
+	uts->old_bootstage_count = bootstage_get_rec_count();
+
 	if (!(test->flags & UTF_NO_SILENT))
 		ut_silence_console(uts);
 
@@ -589,6 +592,8 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
 		log_debug("restore bloblist %p\n", gd_bloblist());
 	}
 
+	bootstage_set_rec_count(uts->old_bootstage_count);
+
 	blkcache_free();
 
 	return 0;
