nordabiz/tests/test_it_audit_collaboration.py
Maciej Pienczyn fa45b4b793 auto-claude: subtask-7-2 - Test collaboration matching
Created comprehensive test suite for IT audit collaboration matching:

1. Unit tests (tests/test_it_audit_collaboration.py):
   - 12 tests verifying all 6 match types
   - Backup replication, shared licensing, Teams federation
   - Shared monitoring, collective purchasing, knowledge sharing
   - Edge cases for size parsing and similarity

2. Integration test script (scripts/test_collaboration_matching.py):
   - Creates test audits with matching criteria
   - Runs collaboration matching algorithm
   - Verifies matches saved to database

All unit tests pass (12/12).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 09:24:45 +01:00

395 lines
14 KiB
Python

"""
Test IT Audit Collaboration Matching
====================================
Tests for the collaboration matching functionality in IT Audit Service.
Test cases:
1. Backup replication matching (Proxmox PBS)
2. Shared licensing matching (M365)
3. Teams federation matching (Azure AD)
4. Shared monitoring matching (Zabbix)
5. Collective purchasing matching (similar size)
6. Knowledge sharing matching (similar tech stack)
Author: Norda Biznes Development Team
Created: 2026-01-09
"""
import os
import sys
import unittest
from unittest.mock import MagicMock, patch
from dataclasses import dataclass
# Add parent directory (worktree root) to path for imports
WORKTREE_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, WORKTREE_ROOT)
# Mock database module before importing it_audit_service
# This prevents database connection errors during import
sys.modules['database'] = MagicMock()
# Now we can safely import it_audit_service
from it_audit_service import ITAuditService, CollaborationMatch
class MockCompany:
"""Mock Company object for testing"""
def __init__(self, id: int, name: str, slug: str):
self.id = id
self.name = name
self.slug = slug
class MockITAudit:
"""Mock ITAudit object for testing"""
def __init__(self, **kwargs):
self.company_id = kwargs.get('company_id', 1)
# Collaboration flags
self.open_to_shared_licensing = kwargs.get('open_to_shared_licensing', False)
self.open_to_backup_replication = kwargs.get('open_to_backup_replication', False)
self.open_to_teams_federation = kwargs.get('open_to_teams_federation', False)
self.open_to_shared_monitoring = kwargs.get('open_to_shared_monitoring', False)
self.open_to_collective_purchasing = kwargs.get('open_to_collective_purchasing', False)
self.open_to_knowledge_sharing = kwargs.get('open_to_knowledge_sharing', False)
# Technology flags
self.has_azure_ad = kwargs.get('has_azure_ad', False)
self.azure_tenant_name = kwargs.get('azure_tenant_name', None)
self.has_m365 = kwargs.get('has_m365', False)
self.m365_plans = kwargs.get('m365_plans', [])
self.has_proxmox_pbs = kwargs.get('has_proxmox_pbs', False)
self.monitoring_solution = kwargs.get('monitoring_solution', None)
# Size info
self.employee_count = kwargs.get('employee_count', None)
# Tech stack
self.virtualization_platform = kwargs.get('virtualization_platform', None)
self.backup_solution = kwargs.get('backup_solution', None)
self.network_firewall_brand = kwargs.get('network_firewall_brand', None)
self.erp_system = kwargs.get('erp_system', None)
class TestCollaborationMatching(unittest.TestCase):
"""Test collaboration matching logic without database"""
def setUp(self):
"""Set up test fixtures"""
# Create service without database (we'll test internal methods)
self.service = ITAuditService.__new__(ITAuditService)
def test_backup_replication_match_both_have_pbs_and_open(self):
"""Test backup replication match when both companies have PBS and are open"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
has_proxmox_pbs=True,
open_to_backup_replication=True
)
audit_b = MockITAudit(
company_id=2,
has_proxmox_pbs=True,
open_to_backup_replication=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
# Should have exactly 1 match for backup_replication
backup_matches = [m for m in matches if m.match_type == 'backup_replication']
self.assertEqual(len(backup_matches), 1)
match = backup_matches[0]
self.assertEqual(match.company_a_id, 1)
self.assertEqual(match.company_b_id, 2)
self.assertEqual(match.match_type, 'backup_replication')
self.assertEqual(match.match_score, 90)
self.assertIn('Proxmox PBS', match.match_reason)
def test_backup_replication_no_match_only_one_has_pbs(self):
"""Test no backup match when only one company has PBS"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
has_proxmox_pbs=True,
open_to_backup_replication=True
)
audit_b = MockITAudit(
company_id=2,
has_proxmox_pbs=False, # Company B doesn't have PBS
open_to_backup_replication=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
backup_matches = [m for m in matches if m.match_type == 'backup_replication']
self.assertEqual(len(backup_matches), 0)
def test_backup_replication_no_match_not_open(self):
"""Test no backup match when one company is not open"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
has_proxmox_pbs=True,
open_to_backup_replication=True
)
audit_b = MockITAudit(
company_id=2,
has_proxmox_pbs=True,
open_to_backup_replication=False # Company B not open
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
backup_matches = [m for m in matches if m.match_type == 'backup_replication']
self.assertEqual(len(backup_matches), 0)
def test_shared_licensing_match_both_have_m365_and_open(self):
"""Test shared licensing match when both have M365 and are open"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
has_m365=True,
m365_plans=['Business Basic', 'E3'],
open_to_shared_licensing=True
)
audit_b = MockITAudit(
company_id=2,
has_m365=True,
m365_plans=['E3', 'E5'],
open_to_shared_licensing=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
licensing_matches = [m for m in matches if m.match_type == 'shared_licensing']
self.assertEqual(len(licensing_matches), 1)
match = licensing_matches[0]
self.assertEqual(match.match_score, 80)
self.assertIn('Microsoft 365', match.match_reason)
def test_teams_federation_match_both_have_azure_ad_and_open(self):
"""Test Teams federation match when both have Azure AD and are open"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
has_azure_ad=True,
azure_tenant_name='firmaa.onmicrosoft.com',
open_to_teams_federation=True
)
audit_b = MockITAudit(
company_id=2,
has_azure_ad=True,
azure_tenant_name='firmab.onmicrosoft.com',
open_to_teams_federation=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
teams_matches = [m for m in matches if m.match_type == 'teams_federation']
self.assertEqual(len(teams_matches), 1)
match = teams_matches[0]
self.assertEqual(match.match_score, 85)
self.assertIn('Azure AD', match.match_reason)
def test_shared_monitoring_match_both_use_zabbix(self):
"""Test shared monitoring match when both use Zabbix"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
monitoring_solution='Zabbix',
open_to_shared_monitoring=True
)
audit_b = MockITAudit(
company_id=2,
monitoring_solution='Zabbix 6.0',
open_to_shared_monitoring=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
monitoring_matches = [m for m in matches if m.match_type == 'shared_monitoring']
self.assertEqual(len(monitoring_matches), 1)
match = monitoring_matches[0]
self.assertEqual(match.match_score, 75)
self.assertIn('Zabbix', match.match_reason)
def test_collective_purchasing_match_similar_size(self):
"""Test collective purchasing match for similar company sizes"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
employee_count='11-50',
open_to_collective_purchasing=True
)
audit_b = MockITAudit(
company_id=2,
employee_count='51-100', # Similar size (within 3x ratio)
open_to_collective_purchasing=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
purchasing_matches = [m for m in matches if m.match_type == 'collective_purchasing']
self.assertEqual(len(purchasing_matches), 1)
match = purchasing_matches[0]
self.assertEqual(match.match_score, 70)
def test_knowledge_sharing_match_similar_tech_stack(self):
"""Test knowledge sharing match for similar tech stack"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
audit_a = MockITAudit(
company_id=1,
virtualization_platform='Proxmox',
backup_solution='Veeam',
has_azure_ad=True,
has_m365=True,
open_to_knowledge_sharing=True
)
audit_b = MockITAudit(
company_id=2,
virtualization_platform='Proxmox',
backup_solution='Veeam',
has_azure_ad=True,
has_m365=True,
open_to_knowledge_sharing=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
knowledge_matches = [m for m in matches if m.match_type == 'knowledge_sharing']
self.assertEqual(len(knowledge_matches), 1)
match = knowledge_matches[0]
self.assertEqual(match.match_score, 65)
# Should have at least 2 common technologies
self.assertIn('common_tech', match.shared_attributes)
self.assertGreaterEqual(len(match.shared_attributes['common_tech']), 2)
def test_multiple_matches_for_same_companies(self):
"""Test that multiple match types can be found for the same company pair"""
company_a = MockCompany(1, "Firma A", "firma-a")
company_b = MockCompany(2, "Firma B", "firma-b")
# Both companies have multiple collaboration opportunities
audit_a = MockITAudit(
company_id=1,
has_proxmox_pbs=True,
has_azure_ad=True,
has_m365=True,
open_to_backup_replication=True,
open_to_teams_federation=True,
open_to_shared_licensing=True
)
audit_b = MockITAudit(
company_id=2,
has_proxmox_pbs=True,
has_azure_ad=True,
has_m365=True,
open_to_backup_replication=True,
open_to_teams_federation=True,
open_to_shared_licensing=True
)
matches = self.service._check_all_match_types(
company_a, audit_a, company_b, audit_b
)
# Should have matches for backup_replication, teams_federation, and shared_licensing
match_types = {m.match_type for m in matches}
self.assertIn('backup_replication', match_types)
self.assertIn('teams_federation', match_types)
self.assertIn('shared_licensing', match_types)
self.assertEqual(len(matches), 3)
def test_parse_count_range(self):
"""Test employee count range parsing"""
self.assertEqual(self.service._parse_count_range('1-10'), 5)
self.assertEqual(self.service._parse_count_range('11-50'), 30)
self.assertEqual(self.service._parse_count_range('51-100'), 75)
self.assertEqual(self.service._parse_count_range('101-250'), 175)
self.assertEqual(self.service._parse_count_range('251-500'), 375)
self.assertEqual(self.service._parse_count_range('500+'), 750)
self.assertIsNone(self.service._parse_count_range(None))
self.assertIsNone(self.service._parse_count_range('unknown'))
def test_sizes_similar(self):
"""Test company size similarity check"""
# Within 3x ratio should be similar
self.assertTrue(self.service._sizes_similar(30, 75)) # 2.5x
self.assertTrue(self.service._sizes_similar(30, 30)) # 1x
self.assertTrue(self.service._sizes_similar(30, 50)) # 1.67x
# More than 3x ratio should not be similar
self.assertFalse(self.service._sizes_similar(5, 175)) # 35x
self.assertFalse(self.service._sizes_similar(5, 750)) # 150x
# Zero handling
self.assertFalse(self.service._sizes_similar(0, 50))
self.assertFalse(self.service._sizes_similar(50, 0))
class TestCollaborationMatchDataclass(unittest.TestCase):
"""Test CollaborationMatch dataclass"""
def test_collaboration_match_creation(self):
"""Test creating a CollaborationMatch"""
match = CollaborationMatch(
company_a_id=1,
company_b_id=2,
company_a_name="Firma A",
company_b_name="Firma B",
match_type="backup_replication",
match_reason="Obie firmy używają Proxmox PBS",
match_score=90,
shared_attributes={"pbs": True}
)
self.assertEqual(match.company_a_id, 1)
self.assertEqual(match.company_b_id, 2)
self.assertEqual(match.match_type, "backup_replication")
self.assertEqual(match.match_score, 90)
self.assertEqual(match.shared_attributes["pbs"], True)
if __name__ == '__main__':
unittest.main(verbosity=2)