FAQ | This is a LIVE service | Changelog

Commit b94207d0 authored by Robin Goodall's avatar Robin Goodall 💬
Browse files

Lookup compare and update tests

parent 2b1c6ded
Pipeline #177402 passed with stages
in 3 minutes and 47 seconds
from typing import Dict, List
from unittest.mock import MagicMock, patch
import pytest
import ibisclient
from . import temp_password_file
from lookupsync.lookup import create_lookup_connection
from lookupsync.lookup import (
create_lookup_connection, compare_with_lookup_groups, update_lookup_groups)
@patch('ibisclient.createConnection')
......@@ -70,3 +75,184 @@ def test_create_lookup_test_connection(
ibis_connect_instance.set_username.assert_called_once_with('TEST_USER')
ibis_connect_instance.set_password.assert_called_once_with('TEST_PASSWORD')
assert ibis_conn == ibis_connect_instance
@pytest.fixture
def mock_students_by_group():
"""
An example dict of Lookup groups to sets of USNs
"""
return {
'foo-sis-ug': {
'123456789',
'234567890',
},
'foo-sis-pg': {
'345678901',
'456789012',
},
'bar-sis-ug': {
'123456789',
'456789012',
'567890123',
}
}
@pytest.fixture
def mock_lookup_group_members(mock_students_by_group):
"""
An example dict of Lookup groups to list of ibisclient.IbisPerson records matching
students_by_group mock
"""
def _make_ibis_person(usn: str):
person = ibisclient.IbisPerson()
identifier = ibisclient.IbisIdentifier()
setattr(identifier, 'scheme', 'usn')
setattr(identifier, 'value', usn)
setattr(person, 'identifiers', [identifier])
return person
return {
group: [_make_ibis_person(usn) for usn in members]
for group, members in mock_students_by_group.items()
}
# Mock ibisclient.GroupMethods
class MockGroupMethods:
def __init__(self, groups: List[Dict[str, ibisclient.IbisPerson]] = list()) -> None:
self.groups = groups
self.updates = {}
def getDirectMembers(self, group, _):
return self.groups[group] # will raise an exception like ibisclient for missing groups
def getGroup(self, group):
return self.groups.get(group)
def updateDirectMembers(self, group, to_add, to_remove, _):
self.updates[group] = {'to_add': to_add, 'to_remove': to_remove}
def test_compare_with_lookup_groups(mock_students_by_group, mock_lookup_group_members):
"""
Matching students_by_group and getDirectMembers responses results in no missing groups or
changes to groups
"""
# Perform comparison
mock_group_methods = MockGroupMethods(mock_lookup_group_members)
missing_groups, group_changes = compare_with_lookup_groups(
mock_group_methods, mock_students_by_group)
# Empty results
assert missing_groups == set()
assert group_changes == dict()
def test_compare_with_lookup_groups_missing_group(
mock_students_by_group, mock_lookup_group_members):
"""
A group in students_by_group but not in getDirectMembers responses results in the group being
reported as missing
"""
# Add a group in mock_student_by_groups that is not in mock_lookup_group_members
NEW_GROUP = 'baz-sis-pg'
assert mock_lookup_group_members.get(NEW_GROUP) is None
mock_students_by_group[NEW_GROUP] = {'999999999'}
# Perform comparison
mock_group_methods = MockGroupMethods(mock_lookup_group_members)
missing_groups, group_changes = compare_with_lookup_groups(
mock_group_methods, mock_students_by_group)
# Just new group reported missing
assert missing_groups == {NEW_GROUP}
assert group_changes == dict()
def test_compare_with_lookup_groups_changes(
mock_students_by_group, mock_lookup_group_members):
"""
Group changes to add and/or remove members are reported
"""
GROUP_TO_ADD_ONLY_TO = 'foo-sis-ug'
GROUP_TO_REMOVE_ONLY_FROM = 'foo-sis-pg'
GROUP_TO_ADD_TO_AND_REMOVE_FROM = 'bar-sis-ug'
USN_TO_ADD = '999999999'
USN_TO_REMOVE = '456789012'
# Assert groups exist
assert GROUP_TO_ADD_ONLY_TO in mock_students_by_group
assert GROUP_TO_REMOVE_ONLY_FROM in mock_students_by_group
assert GROUP_TO_ADD_TO_AND_REMOVE_FROM in mock_students_by_group
# Assert USNs to add don't already exist in appropriate groups
assert USN_TO_ADD not in mock_students_by_group[GROUP_TO_ADD_ONLY_TO]
assert USN_TO_ADD not in mock_students_by_group[GROUP_TO_ADD_TO_AND_REMOVE_FROM]
# Assert USNs to remove do already exist in appropriate groups
assert USN_TO_REMOVE in mock_students_by_group[GROUP_TO_REMOVE_ONLY_FROM]
assert USN_TO_REMOVE in mock_students_by_group[GROUP_TO_ADD_TO_AND_REMOVE_FROM]
# Make changes
mock_students_by_group[GROUP_TO_ADD_ONLY_TO].add(USN_TO_ADD)
mock_students_by_group[GROUP_TO_ADD_TO_AND_REMOVE_FROM].add(USN_TO_ADD)
mock_students_by_group[GROUP_TO_REMOVE_ONLY_FROM].remove(USN_TO_REMOVE)
mock_students_by_group[GROUP_TO_ADD_TO_AND_REMOVE_FROM].remove(USN_TO_REMOVE)
# Perform comparison
mock_group_methods = MockGroupMethods(mock_lookup_group_members)
missing_groups, group_changes = compare_with_lookup_groups(
mock_group_methods, mock_students_by_group)
# No missing groups but appropriate changes reported
assert missing_groups == set()
assert group_changes == {
GROUP_TO_ADD_ONLY_TO: {'add': {USN_TO_ADD}, 'remove': set()},
GROUP_TO_REMOVE_ONLY_FROM: {'add': set(), 'remove': {USN_TO_REMOVE}},
GROUP_TO_ADD_TO_AND_REMOVE_FROM: {'add': {USN_TO_ADD}, 'remove': {USN_TO_REMOVE}},
}
def test_update_lookup_groups():
"""
update_lookup_groups calls updateDirectMembers method of ibisclient.GroupMethods instance
for each group with matching changes
"""
# Group changes with just adds, just removes and both
CHANGES = {
'foo-sis-ug': {'add': {'111', '222'}, 'remove': set()},
'foo-sis-pg': {'add': set(), 'remove': {'333', '444'}},
'bar-sis-ug': {'add': {'555', '666'}, 'remove': {'777', '888'}},
}
mock_group_methods = MockGroupMethods()
# Make update calls (dry-run)
update_lookup_groups(mock_group_methods, CHANGES, True)
# No updateDirectMembers calls made
assert mock_group_methods.updates == {}
# Make update calls (not dry-run)
mock_group_methods = MockGroupMethods()
update_lookup_groups(mock_group_methods, CHANGES, False)
# Each group was updated
assert set(CHANGES.keys()) == set(mock_group_methods.updates.keys())
for group, changes in CHANGES.items():
# Expected call args are prefixed with 'usn/'
expected_to_add = {f'usn/{usn}' for usn in changes['add']}
expected_to_remove = {f'usn/{usn}' for usn in changes['remove']}
# but are lists not sets
assert isinstance(mock_group_methods.updates[group]['to_add'], list)
assert isinstance(mock_group_methods.updates[group]['to_remove'], list)
# however have matching contents
assert expected_to_add == set(mock_group_methods.updates[group]['to_add'])
assert expected_to_remove == set(mock_group_methods.updates[group]['to_remove'])
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment