Skip to content

Commit 254b0d3

Browse files
refactor: cut test execution time (#305)
This PR decreases test execution time for the test_client test suite by about 2 whole minutes (132 seconds, I think). It does that by extracting the `aggregate_metrics` function and, instead of waiting for the client to actually send metrics, just checking what the metrics would be aggregated to. In doing so, it might be worth adding another test to ensure that metrics **are** actually sent, but we may or may not already have this elsewhere. ## Type of change Please delete options that are not relevant. - [x] Refactor of tests # How Has This Been Tested? Please describe the tests that you ran to verify your changes. - [x] Unit tests # Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules
1 parent 232da69 commit 254b0d3

File tree

4 files changed

+50
-52
lines changed

4 files changed

+50
-52
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# ruff: noqa: F401
22
from .fetch_and_load import fetch_and_load_features
3-
from .send_metrics import aggregate_and_send_metrics
3+
from .send_metrics import aggregate_and_send_metrics, aggregate_metrics

UnleashClient/periodic_tasks/send_metrics.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,9 @@
77
from UnleashClient.utils import LOGGER
88

99

10-
def aggregate_and_send_metrics(
11-
url: str,
12-
app_name: str,
13-
instance_id: str,
14-
custom_headers: dict,
15-
custom_options: dict,
10+
def aggregate_metrics(
1611
features: dict,
17-
cache: BaseCache,
18-
request_timeout: int,
19-
) -> None:
12+
) -> dict:
2013
feature_stats_list = []
2114

2215
for feature_name in features.keys():
@@ -31,20 +24,37 @@ def aggregate_and_send_metrics(
3124
}
3225
}
3326

34-
features[feature_name].reset_stats()
3527
feature_stats_list.append(feature_stats)
3628

29+
return dict(ChainMap(*feature_stats_list))
30+
31+
32+
def aggregate_and_send_metrics(
33+
url: str,
34+
app_name: str,
35+
instance_id: str,
36+
custom_headers: dict,
37+
custom_options: dict,
38+
features: dict,
39+
cache: BaseCache,
40+
request_timeout: int,
41+
) -> None:
42+
feature_stats_dict = aggregate_metrics(features)
43+
44+
for feature_name in features.keys():
45+
features[feature_name].reset_stats()
46+
3747
metrics_request = {
3848
"appName": app_name,
3949
"instanceId": instance_id,
4050
"bucket": {
4151
"start": cache.get(METRIC_LAST_SENT_TIME).isoformat(),
4252
"stop": datetime.now(timezone.utc).isoformat(),
43-
"toggles": dict(ChainMap(*feature_stats_list)),
53+
"toggles": feature_stats_dict,
4454
},
4555
}
4656

47-
if feature_stats_list:
57+
if feature_stats_dict:
4858
send_metrics(
4959
url, metrics_request, custom_headers, custom_options, request_timeout
5060
)

tests/unit_tests/test_client.py

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import json
21
import time
32
import warnings
43
from pathlib import Path
@@ -39,6 +38,7 @@
3938
from UnleashClient.cache import FileCache
4039
from UnleashClient.constants import FEATURES_URL, METRICS_URL, REGISTER_URL
4140
from UnleashClient.events import UnleashEvent, UnleashEventType
41+
from UnleashClient.periodic_tasks import aggregate_metrics
4242
from UnleashClient.strategies import Strategy
4343
from UnleashClient.utils import InstanceAllowType
4444

@@ -210,7 +210,7 @@ def test_uc_lifecycle(unleash_client):
210210
status=304,
211211
headers={"etag": ETAG_VALUE},
212212
)
213-
time.sleep(16)
213+
time.sleep(REFRESH_INTERVAL + 1)
214214

215215
# Simulate server provisioning change
216216
responses.add(
@@ -220,7 +220,7 @@ def test_uc_lifecycle(unleash_client):
220220
status=200,
221221
headers={"etag": "W/somethingelse"},
222222
)
223-
time.sleep(30)
223+
time.sleep(REFRESH_INTERVAL * 2)
224224
assert len(unleash_client.features) >= 9
225225

226226

@@ -329,13 +329,13 @@ def test_uc_dirty_cache(unleash_client_nodestroy):
329329

330330
# Create Unleash client and check initial load
331331
unleash_client.initialize_client()
332-
time.sleep(5)
332+
time.sleep(1)
333333
assert unleash_client.is_enabled("testFlag")
334334
unleash_client.unleash_scheduler.shutdown()
335335

336336
# Check that everything works if previous cache exists.
337337
unleash_client.initialize_client()
338-
time.sleep(5)
338+
time.sleep(1)
339339
assert unleash_client.is_enabled("testFlag")
340340

341341

@@ -484,9 +484,8 @@ def test_uc_metrics(unleash_client):
484484
time.sleep(1)
485485
assert unleash_client.is_enabled("testFlag")
486486

487-
time.sleep(12)
488-
request = json.loads(responses.calls[-1].request.body)
489-
assert request["bucket"]["toggles"]["testFlag"]["yes"] == 1
487+
metrics = aggregate_metrics(unleash_client.features)
488+
assert metrics["testFlag"]["yes"] == 1
490489

491490

492491
@responses.activate
@@ -496,7 +495,6 @@ def test_uc_registers_metrics_for_nonexistent_features(unleash_client):
496495
responses.add(
497496
responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200
498497
)
499-
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
500498

501499
# Create Unleash client and check initial load
502500
unleash_client.initialize_client()
@@ -506,9 +504,8 @@ def test_uc_registers_metrics_for_nonexistent_features(unleash_client):
506504
unleash_client.is_enabled("nonexistent-flag")
507505

508506
# Verify that the metrics are serialized
509-
time.sleep(12)
510-
request = json.loads(responses.calls[-1].request.body)
511-
assert request["bucket"]["toggles"]["nonexistent-flag"]["no"] == 1
507+
metrics = aggregate_metrics(unleash_client.features)
508+
assert metrics["nonexistent-flag"]["no"] == 1
512509

513510

514511
@responses.activate
@@ -520,16 +517,14 @@ def test_uc_metrics_dependencies(unleash_client):
520517
json=MOCK_FEATURE_WITH_DEPENDENCIES_RESPONSE,
521518
status=200,
522519
)
523-
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
524520

525521
unleash_client.initialize_client()
526522
time.sleep(1)
527523
assert unleash_client.is_enabled("Child")
528524

529-
time.sleep(12)
530-
request = json.loads(responses.calls[-1].request.body)
531-
assert request["bucket"]["toggles"]["Child"]["yes"] == 1
532-
assert "Parent" not in request["bucket"]["toggles"]
525+
metrics = aggregate_metrics(unleash_client.features)
526+
assert metrics["Child"]["yes"] == 1
527+
assert "Parent" not in metrics
533528

534529

535530
@responses.activate
@@ -539,7 +534,6 @@ def test_uc_registers_variant_metrics_for_nonexistent_features(unleash_client):
539534
responses.add(
540535
responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200
541536
)
542-
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
543537

544538
# Create Unleash client and check initial load
545539
unleash_client.initialize_client()
@@ -548,11 +542,9 @@ def test_uc_registers_variant_metrics_for_nonexistent_features(unleash_client):
548542
# Check a flag that doesn't exist
549543
unleash_client.get_variant("nonexistent-flag")
550544

551-
# Verify that the metrics are serialized
552-
time.sleep(12)
553-
request = json.loads(responses.calls[-1].request.body)
554-
assert request["bucket"]["toggles"]["nonexistent-flag"]["no"] == 1
555-
assert request["bucket"]["toggles"]["nonexistent-flag"]["variants"]["disabled"] == 1
545+
metrics = aggregate_metrics(unleash_client.features)
546+
assert metrics["nonexistent-flag"]["no"] == 1
547+
assert metrics["nonexistent-flag"]["variants"]["disabled"] == 1
556548

557549

558550
@responses.activate
@@ -565,7 +557,6 @@ def test_uc_doesnt_count_metrics_for_dependency_parents(unleash_client):
565557
json=MOCK_FEATURE_WITH_DEPENDENCIES_RESPONSE,
566558
status=200,
567559
)
568-
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
569560

570561
# Create Unleash client and check initial load
571562
unleash_client.initialize_client()
@@ -578,11 +569,10 @@ def test_uc_doesnt_count_metrics_for_dependency_parents(unleash_client):
578569
unleash_client.get_variant(child)
579570

580571
# Verify that the parent doesn't have any metrics registered
581-
time.sleep(12)
582-
request = json.loads(responses.calls[-1].request.body)
583-
assert request["bucket"]["toggles"][child]["yes"] == 2
584-
assert request["bucket"]["toggles"][child]["variants"]["childVariant"] == 1
585-
assert parent not in request["bucket"]["toggles"]
572+
metrics = aggregate_metrics(unleash_client.features)
573+
assert metrics[child]["yes"] == 2
574+
assert metrics[child]["variants"]["childVariant"] == 1
575+
assert parent not in metrics
586576

587577

588578
@responses.activate
@@ -595,7 +585,6 @@ def test_uc_counts_metrics_for_child_even_if_parent_is_disabled(unleash_client):
595585
json=MOCK_FEATURE_WITH_DEPENDENCIES_RESPONSE,
596586
status=200,
597587
)
598-
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
599588

600589
# Create Unleash client and check initial load
601590
unleash_client.initialize_client()
@@ -608,11 +597,10 @@ def test_uc_counts_metrics_for_child_even_if_parent_is_disabled(unleash_client):
608597
unleash_client.get_variant(child)
609598

610599
# Verify that the parent doesn't have any metrics registered
611-
time.sleep(12)
612-
request = json.loads(responses.calls[-1].request.body)
613-
assert request["bucket"]["toggles"][child]["no"] == 2
614-
assert request["bucket"]["toggles"][child]["variants"]["disabled"] == 1
615-
assert parent not in request["bucket"]["toggles"]
600+
metrics = aggregate_metrics(unleash_client.features)
601+
assert metrics[child]["no"] == 2
602+
assert metrics[child]["variants"]["disabled"] == 1
603+
assert parent not in metrics
616604

617605

618606
@responses.activate
@@ -627,7 +615,7 @@ def test_uc_disabled_registration(unleash_client_toggle_only):
627615

628616
unleash_client.initialize_client()
629617
unleash_client.is_enabled("testFlag")
630-
time.sleep(20)
618+
time.sleep(REFRESH_INTERVAL * 2)
631619
assert unleash_client.is_enabled("testFlag")
632620

633621
for api_call in responses.calls:
@@ -650,7 +638,7 @@ def test_uc_server_error(unleash_client):
650638
responses.add(
651639
responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200
652640
)
653-
time.sleep(20)
641+
time.sleep(REFRESH_INTERVAL * 2)
654642
assert unleash_client.is_enabled("testFlag")
655643

656644

tests/utilities/testing_constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
APP_NAME = "pytest"
1515
ENVIRONMENT = "unit"
1616
INSTANCE_ID = "123"
17-
REFRESH_INTERVAL = 15
17+
REFRESH_INTERVAL = 3
1818
REFRESH_JITTER = None
19-
METRICS_INTERVAL = 10
19+
METRICS_INTERVAL = 2
2020
METRICS_JITTER = None
2121
DISABLE_METRICS = True
2222
DISABLE_REGISTRATION = True

0 commit comments

Comments
 (0)