Skip to content

Commit aa29e54

Browse files
committed
Fix module-level side effects and global random seeding in univariate ML anomaly tests
* 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.
1 parent 0140552 commit aa29e54

4 files changed

Lines changed: 39 additions & 36 deletions

File tree

sdks/python/apache_beam/ml/anomaly/univariate/mean_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ def test_with_float64_max(self):
7070

7171
def test_accuracy_fuzz(self):
7272
seed = int(time.time())
73-
random.seed(seed)
73+
rng = random.Random(seed)
7474
print("Random seed: %d" % seed)
7575

7676
for _ in range(10):
7777
numbers = []
7878
for _ in range(5000):
79-
numbers.append(random.randint(0, 1000))
79+
numbers.append(rng.randint(0, 1000))
8080

8181
with warnings.catch_warnings(record=False):
8282
warnings.simplefilter("ignore")
@@ -140,13 +140,13 @@ def test_with_float64_max(self, tracker):
140140

141141
def test_accuracy_fuzz(self):
142142
seed = int(time.time())
143-
random.seed(seed)
143+
rng = random.Random(seed)
144144
print("Random seed: %d" % seed)
145145

146146
for _ in range(10):
147147
numbers = []
148148
for _ in range(5000):
149-
numbers.append(random.randint(0, 1000))
149+
numbers.append(rng.randint(0, 1000))
150150

151151
t1 = IncSlidingMeanTracker(100)
152152
t2 = SimpleSlidingMeanTracker(100)

sdks/python/apache_beam/ml/anomaly/univariate/perf_test.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,54 +27,57 @@
2727
from apache_beam.ml.anomaly.univariate.quantile import *
2828
from apache_beam.ml.anomaly.univariate.stdev import *
2929

30-
seed_value_time = int(time.time())
31-
random.seed(seed_value_time)
32-
print(f"{'Seed value':32s}{seed_value_time}")
33-
34-
numbers = []
35-
for _ in range(50000):
36-
numbers.append(random.randint(0, 1000))
37-
3830

3931
def run_tracker(tracker, numbers):
4032
for i in range(len(numbers)):
4133
tracker.push(numbers[i])
4234
_ = tracker.get()
4335

4436

45-
def print_result(tracker, number=10, repeat=5):
46-
runtimes = timeit.repeat(
47-
lambda: run_tracker(tracker, numbers), number=number, repeat=repeat)
48-
mean = statistics.mean(runtimes)
49-
sd = statistics.stdev(runtimes)
50-
print(f"{tracker.__class__.__name__:32s}{mean:.6f} ± {sd:.6f}")
37+
class PerfTest(unittest.TestCase):
38+
@classmethod
39+
def setUpClass(cls):
40+
seed_value_time = int(time.time())
41+
rng = random.Random(seed_value_time)
42+
print(f"{'Seed value':32s}{seed_value_time}")
5143

44+
cls.numbers = []
45+
for _ in range(50000):
46+
cls.numbers.append(rng.randint(0, 1000))
47+
48+
def print_result(self, tracker, number=10, repeat=5):
49+
runtimes = timeit.repeat(
50+
lambda: run_tracker(tracker, self.numbers),
51+
number=number,
52+
repeat=repeat)
53+
mean = statistics.mean(runtimes)
54+
sd = statistics.stdev(runtimes)
55+
print(f"{tracker.__class__.__name__:32s}{mean:.6f} ± {sd:.6f}")
5256

53-
class PerfTest(unittest.TestCase):
5457
def test_mean_perf(self):
5558
print()
56-
print_result(IncLandmarkMeanTracker())
57-
print_result(IncSlidingMeanTracker(100))
59+
self.print_result(IncLandmarkMeanTracker())
60+
self.print_result(IncSlidingMeanTracker(100))
5861
# SimpleSlidingMeanTracker (numpy-based batch approach) is an order of
5962
# magnitude slower than other methods. To prevent excessively long test
6063
# runs, we reduce the number of repetitions.
61-
print_result(SimpleSlidingMeanTracker(100), number=1)
64+
self.print_result(SimpleSlidingMeanTracker(100), number=1)
6265

6366
def test_stdev_perf(self):
6467
print()
65-
print_result(IncLandmarkStdevTracker())
66-
print_result(IncSlidingStdevTracker(100))
68+
self.print_result(IncLandmarkStdevTracker())
69+
self.print_result(IncSlidingStdevTracker(100))
6770
# Same as test_mean_perf, we reduce the number of repetitions here.
68-
print_result(SimpleSlidingStdevTracker(100), number=1)
71+
self.print_result(SimpleSlidingStdevTracker(100), number=1)
6972

7073
def test_quantile_perf(self):
7174
print()
7275
with warnings.catch_warnings(record=False):
7376
warnings.simplefilter("ignore")
74-
print_result(BufferedLandmarkQuantileTracker(0.5))
75-
print_result(BufferedSlidingQuantileTracker(100, 0.5))
77+
self.print_result(BufferedLandmarkQuantileTracker(0.5))
78+
self.print_result(BufferedSlidingQuantileTracker(100, 0.5))
7679
# Same as test_mean_perf, we reduce the number of repetitions here.
77-
print_result(SimpleSlidingQuantileTracker(100, 0.5), number=1)
80+
self.print_result(SimpleSlidingQuantileTracker(100, 0.5), number=1)
7881

7982

8083
if __name__ == '__main__':

sdks/python/apache_beam/ml/anomaly/univariate/quantile_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ def test_with_nan(self):
6868

6969
def test_accuracy_fuzz(self):
7070
seed = int(time.time())
71-
random.seed(seed)
71+
rng = random.Random(seed)
7272
print("Random seed: %d" % seed)
7373

7474
def _accuracy_helper():
7575
numbers = []
7676
for _ in range(5000):
77-
numbers.append(random.randint(0, 1000))
77+
numbers.append(rng.randint(0, 1000))
7878

7979
with warnings.catch_warnings(record=False):
8080
warnings.simplefilter("ignore")
@@ -138,13 +138,13 @@ def test_with_nan(self, tracker):
138138

139139
def test_accuracy_fuzz(self):
140140
seed = int(time.time())
141-
random.seed(seed)
141+
rng = random.Random(seed)
142142
print("Random seed: %d" % seed)
143143

144144
def _accuracy_helper():
145145
numbers = []
146146
for _ in range(5000):
147-
numbers.append(random.randint(0, 1000))
147+
numbers.append(rng.randint(0, 1000))
148148

149149
t1 = BufferedSlidingQuantileTracker(100, 0.1)
150150
t2 = SimpleSlidingQuantileTracker(100, 0.1)

sdks/python/apache_beam/ml/anomaly/univariate/stdev_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ def test_with_nan(self):
6666

6767
def test_accuracy_fuzz(self):
6868
seed = int(time.time())
69-
random.seed(seed)
69+
rng = random.Random(seed)
7070
print("Random seed: %d" % seed)
7171

7272
for _ in range(10):
7373
numbers = []
7474
for _ in range(5000):
75-
numbers.append(random.randint(0, 1000))
75+
numbers.append(rng.randint(0, 1000))
7676

7777
t1 = IncLandmarkStdevTracker()
7878
t2 = SimpleSlidingStdevTracker(len(numbers))
@@ -135,13 +135,13 @@ def test_stdev_with_nan(self, tracker):
135135

136136
def test_accuracy_fuzz(self):
137137
seed = int(time.time())
138-
random.seed(seed)
138+
rng = random.Random(seed)
139139
print("Random seed: %d" % seed)
140140

141141
for _ in range(10):
142142
numbers = []
143143
for _ in range(5000):
144-
numbers.append(random.randint(0, 1000))
144+
numbers.append(rng.randint(0, 1000))
145145

146146
t1 = IncSlidingStdevTracker(100)
147147
t2 = SimpleSlidingStdevTracker(100)

0 commit comments

Comments
 (0)