Add a stress test to validate a significant set of settings
This commit is contained in:
parent
1bef611806
commit
01b7f1d249
1 changed files with 146 additions and 99 deletions
245
matching_test.py
245
matching_test.py
|
@ -3,6 +3,7 @@
|
|||
"""
|
||||
import discord
|
||||
import pytest
|
||||
import random
|
||||
import matching
|
||||
import history
|
||||
from datetime import datetime, timedelta
|
||||
|
@ -15,7 +16,7 @@ def test_protocols():
|
|||
assert isinstance(discord.Role, matching.Role)
|
||||
|
||||
|
||||
class TestMember():
|
||||
class Member():
|
||||
def __init__(self, id: int):
|
||||
self._id = id
|
||||
|
||||
|
@ -32,104 +33,8 @@ class TestMember():
|
|||
self._id = value
|
||||
|
||||
|
||||
@pytest.mark.parametrize("matchees, per_group", [
|
||||
# Simplest test possible
|
||||
([TestMember(1)], 1),
|
||||
|
||||
# More requested than we have
|
||||
([TestMember(1)], 2),
|
||||
|
||||
# A selection of hyper-simple checks to validate core functionality
|
||||
([TestMember(1)] * 100, 3),
|
||||
([TestMember(1)] * 12, 5),
|
||||
([TestMember(1)] * 11, 2),
|
||||
([TestMember(1)] * 356, 8),
|
||||
])
|
||||
def test_matchees_to_groups_no_history(matchees, per_group):
|
||||
"""Test simple group matching works"""
|
||||
hist = history.History()
|
||||
core_validate_members_to_groups(matchees, hist, per_group)
|
||||
|
||||
|
||||
def items_found_in_lists(list_of_lists, items):
|
||||
"""validates if any sets of items are found in individual lists"""
|
||||
for sublist in list_of_lists:
|
||||
if all(item in sublist for item in items):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@pytest.mark.parametrize("history_data, matchees, per_group, checks", [
|
||||
# Slightly more difficult test
|
||||
# Describe a history where we previously matched up some people and ensure they don't get rematched
|
||||
(
|
||||
[
|
||||
{
|
||||
"ts": datetime.now() - timedelta(days=1),
|
||||
"groups": [
|
||||
[TestMember(1), TestMember(2)],
|
||||
[TestMember(3), TestMember(4)],
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
TestMember(1),
|
||||
TestMember(2),
|
||||
TestMember(3),
|
||||
TestMember(4),
|
||||
],
|
||||
2,
|
||||
[
|
||||
lambda groups: not items_found_in_lists(
|
||||
groups, [TestMember(1), TestMember(2)]),
|
||||
lambda groups: not items_found_in_lists(
|
||||
groups, [TestMember(3), TestMember(4)])
|
||||
]
|
||||
),
|
||||
# Feed the system an "impossible" test
|
||||
# The function should fall back to ignoring history and still give us something
|
||||
(
|
||||
[
|
||||
{
|
||||
"ts": datetime.now() - timedelta(days=1),
|
||||
"groups": [
|
||||
[TestMember(1), TestMember(2), TestMember(3)],
|
||||
[TestMember(4), TestMember(5), TestMember(6)],
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
TestMember(1),
|
||||
TestMember(2),
|
||||
TestMember(3),
|
||||
TestMember(4),
|
||||
TestMember(5),
|
||||
TestMember(6),
|
||||
],
|
||||
3,
|
||||
[
|
||||
# Nothing specific to validate
|
||||
]
|
||||
),
|
||||
|
||||
])
|
||||
def test_matchees_to_groups_with_history(history_data, matchees, per_group, checks):
|
||||
"""Test simple group matching works"""
|
||||
hist = history.History()
|
||||
|
||||
# Replay the history
|
||||
for d in history_data:
|
||||
hist.log_groups_to_history(d["groups"], d["ts"])
|
||||
|
||||
groups = core_validate_members_to_groups(matchees, hist, per_group)
|
||||
|
||||
# Run the custom validate functions
|
||||
for check in checks:
|
||||
assert check(groups)
|
||||
|
||||
|
||||
def core_validate_members_to_groups(matchees: list[TestMember], hist: history.History, per_group: int):
|
||||
# Convert members to groups
|
||||
def inner_validate_members_to_groups(matchees: list[Member], hist: history.History, per_group: int):
|
||||
"""Inner function to validate the main output of the groups function"""
|
||||
groups = matching.members_to_groups(matchees, hist, per_group)
|
||||
|
||||
# We should always have one group
|
||||
|
@ -148,3 +53,145 @@ def core_validate_members_to_groups(matchees: list[TestMember], hist: history.Hi
|
|||
assert len(group) < per_group*2 # TODO: We could be more strict here
|
||||
|
||||
return groups
|
||||
|
||||
|
||||
@pytest.mark.parametrize("matchees, per_group", [
|
||||
# Simplest test possible
|
||||
([Member(1)], 1),
|
||||
|
||||
# More requested than we have
|
||||
([Member(1)], 2),
|
||||
|
||||
# A selection of hyper-simple checks to validate core functionality
|
||||
([Member(1)] * 100, 3),
|
||||
([Member(1)] * 12, 5),
|
||||
([Member(1)] * 11, 2),
|
||||
([Member(1)] * 356, 8),
|
||||
])
|
||||
def test_members_to_groups_no_history(matchees, per_group):
|
||||
"""Test simple group matching works"""
|
||||
hist = history.History()
|
||||
inner_validate_members_to_groups(matchees, hist, per_group)
|
||||
|
||||
|
||||
def items_found_in_lists(list_of_lists, items):
|
||||
"""validates if any sets of items are found in individual lists"""
|
||||
for sublist in list_of_lists:
|
||||
if all(item in sublist for item in items):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@pytest.mark.parametrize("history_data, matchees, per_group, checks", [
|
||||
# Slightly more difficult test
|
||||
# Describe a history where we previously matched up some people and ensure they don't get rematched
|
||||
(
|
||||
[
|
||||
{
|
||||
"ts": datetime.now() - timedelta(days=1),
|
||||
"groups": [
|
||||
[Member(1), Member(2)],
|
||||
[Member(3), Member(4)],
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
Member(1),
|
||||
Member(2),
|
||||
Member(3),
|
||||
Member(4),
|
||||
],
|
||||
2,
|
||||
[
|
||||
lambda groups: not items_found_in_lists(
|
||||
groups, [Member(1), Member(2)]),
|
||||
lambda groups: not items_found_in_lists(
|
||||
groups, [Member(3), Member(4)])
|
||||
]
|
||||
),
|
||||
# Feed the system an "impossible" test
|
||||
# The function should fall back to ignoring history and still give us something
|
||||
(
|
||||
[
|
||||
{
|
||||
"ts": datetime.now() - timedelta(days=1),
|
||||
"groups": [
|
||||
[Member(1), Member(2), Member(3)],
|
||||
[Member(4), Member(5), Member(6)],
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
Member(1),
|
||||
Member(2),
|
||||
Member(3),
|
||||
Member(4),
|
||||
Member(5),
|
||||
Member(6),
|
||||
],
|
||||
3,
|
||||
[
|
||||
# Nothing specific to validate
|
||||
]
|
||||
),
|
||||
])
|
||||
def test_members_to_groups_with_history(history_data, matchees, per_group, checks):
|
||||
"""Test more advanced group matching works"""
|
||||
hist = history.History()
|
||||
|
||||
# Replay the history
|
||||
for d in history_data:
|
||||
hist.log_groups_to_history(d["groups"], d["ts"])
|
||||
|
||||
groups = inner_validate_members_to_groups(matchees, hist, per_group)
|
||||
|
||||
# Run the custom validate functions
|
||||
for check in checks:
|
||||
assert check(groups)
|
||||
|
||||
|
||||
def test_members_to_groups_stress_test():
|
||||
"""stress test firing significant random data at the code"""
|
||||
|
||||
# Use a stable rand, feel free to adjust this if needed but this lets the test be stable
|
||||
rand = random.Random(123)
|
||||
|
||||
# Slowly ramp up the group size
|
||||
for per_group in range(1, 5):
|
||||
|
||||
# Slowly ramp a randomized shuffled list of members
|
||||
for num_members in range(1, 5):
|
||||
# up to 50 total members
|
||||
matchees = list(Member(i)
|
||||
for i in range(1, rand.randint(2, num_members*10 + 1)))
|
||||
rand.shuffle(matchees)
|
||||
|
||||
for num_history in range(8):
|
||||
|
||||
# Generate some super random history
|
||||
# Start some time from now to the past
|
||||
time = datetime.now() - timedelta(days=rand.randint(0, num_history*5))
|
||||
history_data = []
|
||||
for x in range(0, num_history):
|
||||
run = {
|
||||
"ts": time
|
||||
}
|
||||
groups = []
|
||||
for y in range(1, num_history):
|
||||
groups.append(list(Member(i)
|
||||
for i in range(1, max(num_members, rand.randint(2, num_members*10 + 1)))))
|
||||
run["groups"] = groups
|
||||
history_data.append(run)
|
||||
|
||||
# Step some time backwards in time
|
||||
time -= timedelta(days=rand.randint(1, num_history))
|
||||
|
||||
# No guarantees on history data order so make it a little harder for matchy
|
||||
rand.shuffle(history_data)
|
||||
|
||||
# Replay the history
|
||||
hist = history.History()
|
||||
for d in history_data:
|
||||
hist.log_groups_to_history(d["groups"], d["ts"])
|
||||
|
||||
inner_validate_members_to_groups(matchees, hist, per_group)
|
||||
|
|
Loading…
Add table
Reference in a new issue