matchy/matching_test.py

151 lines
4.1 KiB
Python
Raw Normal View History

2024-08-09 23:14:42 +01:00
"""
Test functions for Matchy
"""
import discord
import pytest
import matching
import history
from datetime import datetime, timedelta
def test_protocols():
"""Verify the protocols we're using match the discord ones"""
assert isinstance(discord.Member, matching.Member)
assert isinstance(discord.Guild, matching.Guild)
assert isinstance(discord.Role, matching.Role)
class TestMember():
def __init__(self, id: int):
self._id = id
@property
def mention(self) -> str:
return f"<@{self._id}>"
@property
def id(self) -> int:
return self._id
@id.setter
def id(self, value):
self._id = value
2024-08-09 23:14:42 +01:00
@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
]
),
2024-08-09 23:14:42 +01:00
])
def test_matchees_to_groups_with_history(history_data, matchees, per_group, checks):
2024-08-09 23:14:42 +01:00
"""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
groups = matching.members_to_groups(matchees, hist, per_group)
# We should always have one group
assert len(groups)
# Log the groups to history
# This will validate the internals
hist.log_groups_to_history(groups)
# Ensure each group contains within the bounds of expected members
2024-08-09 23:14:42 +01:00
for group in groups:
if len(matchees) >= per_group:
assert len(group) >= per_group
else:
assert len(group) == len(matchees)
assert len(group) < per_group*2 # TODO: We could be more strict here
return groups