This is an automated email from the ASF dual-hosted git repository.

shunping pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 4f934835059 Fix module-level side effects and global random seeding in 
univariate ML anomaly tests (#39462)
4f934835059 is described below

commit 4f9348350592c56f5eada496df555f8dfd4497f5
Author: Yi Hu <[email protected]>
AuthorDate: Thu Jul 30 11:58:48 2026 -0400

    Fix module-level side effects and global random seeding in univariate ML 
anomaly tests (#39462)
    
    * Remove top-level dataset generation, stdout printing, and global seeding 
from perf_test.py by moving setup logic into PerfTest.setUpClass.
    
    * Replace calls to global random.seed() in perf_test.py, mean_test.py, 
quantile_test.py, and stdev_test.py with isolated random.Random instances.
      This prevents state leakage and unneeded computation when modules are 
imported during test collection.
---
 .../apache_beam/ml/anomaly/univariate/mean_test.py |  8 ++--
 .../apache_beam/ml/anomaly/univariate/perf_test.py | 51 ++++++++++++----------
 .../ml/anomaly/univariate/quantile_test.py         |  8 ++--
 .../ml/anomaly/univariate/stdev_test.py            |  8 ++--
 4 files changed, 39 insertions(+), 36 deletions(-)

diff --git a/sdks/python/apache_beam/ml/anomaly/univariate/mean_test.py 
b/sdks/python/apache_beam/ml/anomaly/univariate/mean_test.py
index 0c8888597eb..d0d7a62e4ce 100644
--- a/sdks/python/apache_beam/ml/anomaly/univariate/mean_test.py
+++ b/sdks/python/apache_beam/ml/anomaly/univariate/mean_test.py
@@ -70,13 +70,13 @@ class LandmarkMeanTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     for _ in range(10):
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       with warnings.catch_warnings(record=False):
         warnings.simplefilter("ignore")
@@ -140,13 +140,13 @@ class SlidingMeanTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     for _ in range(10):
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       t1 = IncSlidingMeanTracker(100)
       t2 = SimpleSlidingMeanTracker(100)
diff --git a/sdks/python/apache_beam/ml/anomaly/univariate/perf_test.py 
b/sdks/python/apache_beam/ml/anomaly/univariate/perf_test.py
index 61067ef38da..9bb4004cf0e 100644
--- a/sdks/python/apache_beam/ml/anomaly/univariate/perf_test.py
+++ b/sdks/python/apache_beam/ml/anomaly/univariate/perf_test.py
@@ -27,14 +27,6 @@ from apache_beam.ml.anomaly.univariate.mean import *
 from apache_beam.ml.anomaly.univariate.quantile import *
 from apache_beam.ml.anomaly.univariate.stdev import *
 
-seed_value_time = int(time.time())
-random.seed(seed_value_time)
-print(f"{'Seed value':32s}{seed_value_time}")
-
-numbers = []
-for _ in range(50000):
-  numbers.append(random.randint(0, 1000))
-
 
 def run_tracker(tracker, numbers):
   for i in range(len(numbers)):
@@ -42,39 +34,50 @@ def run_tracker(tracker, numbers):
     _ = tracker.get()
 
 
-def print_result(tracker, number=10, repeat=5):
-  runtimes = timeit.repeat(
-      lambda: run_tracker(tracker, numbers), number=number, repeat=repeat)
-  mean = statistics.mean(runtimes)
-  sd = statistics.stdev(runtimes)
-  print(f"{tracker.__class__.__name__:32s}{mean:.6f} ± {sd:.6f}")
+class PerfTest(unittest.TestCase):
+  @classmethod
+  def setUpClass(cls):
+    seed_value_time = int(time.time())
+    rng = random.Random(seed_value_time)
+    print(f"{'Seed value':32s}{seed_value_time}")
 
+    cls.numbers = []
+    for _ in range(50000):
+      cls.numbers.append(rng.randint(0, 1000))
+
+  def print_result(self, tracker, number=10, repeat=5):
+    runtimes = timeit.repeat(
+        lambda: run_tracker(tracker, self.numbers),
+        number=number,
+        repeat=repeat)
+    mean = statistics.mean(runtimes)
+    sd = statistics.stdev(runtimes)
+    print(f"{tracker.__class__.__name__:32s}{mean:.6f} ± {sd:.6f}")
 
-class PerfTest(unittest.TestCase):
   def test_mean_perf(self):
     print()
-    print_result(IncLandmarkMeanTracker())
-    print_result(IncSlidingMeanTracker(100))
+    self.print_result(IncLandmarkMeanTracker())
+    self.print_result(IncSlidingMeanTracker(100))
     # SimpleSlidingMeanTracker (numpy-based batch approach) is an order of
     # magnitude slower than other methods. To prevent excessively long test
     # runs, we reduce the number of repetitions.
-    print_result(SimpleSlidingMeanTracker(100), number=1)
+    self.print_result(SimpleSlidingMeanTracker(100), number=1)
 
   def test_stdev_perf(self):
     print()
-    print_result(IncLandmarkStdevTracker())
-    print_result(IncSlidingStdevTracker(100))
+    self.print_result(IncLandmarkStdevTracker())
+    self.print_result(IncSlidingStdevTracker(100))
     # Same as test_mean_perf, we reduce the number of repetitions here.
-    print_result(SimpleSlidingStdevTracker(100), number=1)
+    self.print_result(SimpleSlidingStdevTracker(100), number=1)
 
   def test_quantile_perf(self):
     print()
     with warnings.catch_warnings(record=False):
       warnings.simplefilter("ignore")
-      print_result(BufferedLandmarkQuantileTracker(0.5))
-    print_result(BufferedSlidingQuantileTracker(100, 0.5))
+      self.print_result(BufferedLandmarkQuantileTracker(0.5))
+    self.print_result(BufferedSlidingQuantileTracker(100, 0.5))
     # Same as test_mean_perf, we reduce the number of repetitions here.
-    print_result(SimpleSlidingQuantileTracker(100, 0.5), number=1)
+    self.print_result(SimpleSlidingQuantileTracker(100, 0.5), number=1)
 
 
 if __name__ == '__main__':
diff --git a/sdks/python/apache_beam/ml/anomaly/univariate/quantile_test.py 
b/sdks/python/apache_beam/ml/anomaly/univariate/quantile_test.py
index 9f9402505b7..427c66a964b 100644
--- a/sdks/python/apache_beam/ml/anomaly/univariate/quantile_test.py
+++ b/sdks/python/apache_beam/ml/anomaly/univariate/quantile_test.py
@@ -68,13 +68,13 @@ class LandmarkQuantileTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     def _accuracy_helper():
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       with warnings.catch_warnings(record=False):
         warnings.simplefilter("ignore")
@@ -138,13 +138,13 @@ class SlidingQuantileTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     def _accuracy_helper():
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       t1 = BufferedSlidingQuantileTracker(100, 0.1)
       t2 = SimpleSlidingQuantileTracker(100, 0.1)
diff --git a/sdks/python/apache_beam/ml/anomaly/univariate/stdev_test.py 
b/sdks/python/apache_beam/ml/anomaly/univariate/stdev_test.py
index c26f16e3a1b..f29fdccd91e 100644
--- a/sdks/python/apache_beam/ml/anomaly/univariate/stdev_test.py
+++ b/sdks/python/apache_beam/ml/anomaly/univariate/stdev_test.py
@@ -66,13 +66,13 @@ class LandmarkStdevTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     for _ in range(10):
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       t1 = IncLandmarkStdevTracker()
       t2 = SimpleSlidingStdevTracker(len(numbers))
@@ -135,13 +135,13 @@ class SlidingStdevTest(unittest.TestCase):
 
   def test_accuracy_fuzz(self):
     seed = int(time.time())
-    random.seed(seed)
+    rng = random.Random(seed)
     print("Random seed: %d" % seed)
 
     for _ in range(10):
       numbers = []
       for _ in range(5000):
-        numbers.append(random.randint(0, 1000))
+        numbers.append(rng.randint(0, 1000))
 
       t1 = IncSlidingStdevTracker(100)
       t2 = SimpleSlidingStdevTracker(100)

Reply via email to