|
"""
|
|
اختبارات تكامل للوحة المعلومات
|
|
"""
|
|
|
|
import unittest
|
|
import pandas as pd
|
|
import numpy as np
|
|
import os
|
|
import sys
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
|
|
|
|
from modules.reports.reports_app import ReportsApp
|
|
import streamlit as st
|
|
|
|
|
|
class TestDashboard(unittest.TestCase):
|
|
"""اختبارات تكامل للوحة المعلومات"""
|
|
|
|
def setUp(self):
|
|
"""إعداد بيئة الاختبار"""
|
|
self.reports_app = ReportsApp()
|
|
|
|
|
|
self.mock_projects = [
|
|
{
|
|
'id': 1,
|
|
'name': 'مشروع 1',
|
|
'number': 'T-2024001',
|
|
'client': 'وزارة الصحة',
|
|
'location': 'الرياض',
|
|
'status': 'جديد',
|
|
'submission_date': '2024-01-15',
|
|
'tender_type': 'عامة',
|
|
'created_at': '2024-01-10',
|
|
'value': 1500000,
|
|
'local_content': 75
|
|
},
|
|
{
|
|
'id': 2,
|
|
'name': 'مشروع 2',
|
|
'number': 'T-2024002',
|
|
'client': 'وزارة التعليم',
|
|
'location': 'جدة',
|
|
'status': 'قيد التسعير',
|
|
'submission_date': '2024-01-28',
|
|
'tender_type': 'خاصة',
|
|
'created_at': '2024-01-20',
|
|
'value': 4500000,
|
|
'local_content': 80
|
|
},
|
|
{
|
|
'id': 3,
|
|
'name': 'مشروع 3',
|
|
'number': 'T-2024003',
|
|
'client': 'وزارة الصحة',
|
|
'location': 'الدمام',
|
|
'status': 'تم التقديم',
|
|
'submission_date': '2024-02-10',
|
|
'tender_type': 'عامة',
|
|
'created_at': '2024-02-01',
|
|
'value': 8000000,
|
|
'local_content': 70
|
|
},
|
|
{
|
|
'id': 4,
|
|
'name': 'مشروع 4',
|
|
'number': 'T-2024004',
|
|
'client': 'شركة أرامكو',
|
|
'location': 'الظهران',
|
|
'status': 'تمت الترسية',
|
|
'submission_date': '2024-02-15',
|
|
'tender_type': 'عامة',
|
|
'created_at': '2024-02-05',
|
|
'value': 15000000,
|
|
'local_content': 85
|
|
},
|
|
{
|
|
'id': 5,
|
|
'name': 'مشروع 5',
|
|
'number': 'T-2024005',
|
|
'client': 'شركة سابك',
|
|
'location': 'الجبيل',
|
|
'status': 'قيد التنفيذ',
|
|
'submission_date': '2024-02-20',
|
|
'tender_type': 'خاصة',
|
|
'created_at': '2024-02-10',
|
|
'value': 25000000,
|
|
'local_content': 75
|
|
},
|
|
{
|
|
'id': 6,
|
|
'name': 'مشروع 6',
|
|
'number': 'T-2024006',
|
|
'client': 'وزارة النقل',
|
|
'location': 'الرياض',
|
|
'status': 'منتهي',
|
|
'submission_date': '2024-01-05',
|
|
'tender_type': 'عامة',
|
|
'created_at': '2023-12-20',
|
|
'value': 5000000,
|
|
'local_content': 72
|
|
},
|
|
{
|
|
'id': 7,
|
|
'name': 'مشروع 7',
|
|
'number': 'T-2024007',
|
|
'client': 'وزارة الإسكان',
|
|
'location': 'مكة',
|
|
'status': 'ملغي',
|
|
'submission_date': '2024-01-10',
|
|
'tender_type': 'خاصة',
|
|
'created_at': '2023-12-25',
|
|
'value': 12000000,
|
|
'local_content': 65
|
|
}
|
|
]
|
|
|
|
|
|
st.session_state.projects = self.mock_projects
|
|
|
|
def test_dashboard_metrics(self):
|
|
"""اختبار مؤشرات لوحة المعلومات الرئيسية"""
|
|
|
|
total_projects = self.reports_app._get_total_projects()
|
|
active_projects = self.reports_app._get_active_projects()
|
|
won_projects = self.reports_app._get_won_projects()
|
|
avg_local_content = self.reports_app._get_avg_local_content()
|
|
|
|
|
|
self.assertEqual(total_projects, 7)
|
|
self.assertEqual(active_projects, 4)
|
|
self.assertEqual(won_projects, 3)
|
|
|
|
|
|
expected_avg_local_content = sum(p['local_content'] for p in self.mock_projects) / len(self.mock_projects)
|
|
self.assertAlmostEqual(avg_local_content, expected_avg_local_content, delta=1.0)
|
|
|
|
def test_project_status_distribution(self):
|
|
"""اختبار توزيع المشاريع حسب الحالة"""
|
|
|
|
status_data = self.reports_app._get_project_status_data()
|
|
|
|
|
|
self.assertIsInstance(status_data, pd.DataFrame)
|
|
|
|
|
|
self.assertIn('status', status_data.columns)
|
|
self.assertIn('count', status_data.columns)
|
|
|
|
|
|
self.assertEqual(len(status_data), 7)
|
|
|
|
|
|
self.assertEqual(status_data['count'].sum(), 7)
|
|
|
|
|
|
status_counts = status_data.set_index('status')['count'].to_dict()
|
|
self.assertEqual(status_counts['جديد'], 1)
|
|
self.assertEqual(status_counts['قيد التسعير'], 1)
|
|
self.assertEqual(status_counts['تم التقديم'], 1)
|
|
self.assertEqual(status_counts['تمت الترسية'], 1)
|
|
self.assertEqual(status_counts['قيد التنفيذ'], 1)
|
|
self.assertEqual(status_counts['منتهي'], 1)
|
|
self.assertEqual(status_counts['ملغي'], 1)
|
|
|
|
def test_monthly_trend_data(self):
|
|
"""اختبار بيانات الاتجاه الشهري"""
|
|
|
|
monthly_data = self.reports_app._get_monthly_project_data()
|
|
|
|
|
|
self.assertIsInstance(monthly_data, pd.DataFrame)
|
|
|
|
|
|
self.assertIn('month', monthly_data.columns)
|
|
self.assertIn('new', monthly_data.columns)
|
|
self.assertIn('submitted', monthly_data.columns)
|
|
self.assertIn('won', monthly_data.columns)
|
|
|
|
|
|
self.assertEqual(len(monthly_data), 6)
|
|
|
|
def test_project_value_distribution(self):
|
|
"""اختبار توزيع المشاريع حسب القيمة"""
|
|
|
|
value_data = self.reports_app._get_project_value_data()
|
|
|
|
|
|
self.assertIsInstance(value_data, pd.DataFrame)
|
|
|
|
|
|
self.assertIn('range', value_data.columns)
|
|
self.assertIn('count', value_data.columns)
|
|
|
|
|
|
self.assertEqual(len(value_data), 7)
|
|
|
|
|
|
self.assertEqual(value_data['count'].sum(), 7)
|
|
|
|
|
|
value_ranges = value_data['range'].tolist()
|
|
self.assertIn('أقل من 1 مليون', value_ranges)
|
|
self.assertIn('1-5 مليون', value_ranges)
|
|
self.assertIn('5-10 مليون', value_ranges)
|
|
self.assertIn('10-20 مليون', value_ranges)
|
|
self.assertIn('20-50 مليون', value_ranges)
|
|
|
|
def test_custom_report_generation(self):
|
|
"""اختبار إنشاء التقارير المخصصة"""
|
|
|
|
table_data = self.reports_app._generate_sample_data(
|
|
data_source="المشاريع",
|
|
fields=["اسم المشروع", "العميل", "الحالة", "تاريخ التقديم"],
|
|
rows=10
|
|
)
|
|
|
|
|
|
self.assertIsInstance(table_data, pd.DataFrame)
|
|
self.assertEqual(len(table_data), 10)
|
|
self.assertEqual(len(table_data.columns), 4)
|
|
|
|
|
|
filters = [
|
|
{
|
|
'field': 'العميل',
|
|
'operator': 'يساوي',
|
|
'value': 'وزارة الصحة'
|
|
}
|
|
]
|
|
|
|
filtered_data = table_data.copy()
|
|
for filter_info in filters:
|
|
field = filter_info['field']
|
|
operator = filter_info['operator']
|
|
value = filter_info['value']
|
|
|
|
if field in filtered_data.columns:
|
|
if operator == "يساوي":
|
|
filtered_data = filtered_data[filtered_data[field] == value]
|
|
|
|
|
|
if not filtered_data.empty:
|
|
self.assertTrue(all(client == 'وزارة الصحة' for client in filtered_data['العميل']))
|
|
|
|
def test_report_export_functionality(self):
|
|
"""اختبار وظيفة تصدير التقارير"""
|
|
|
|
|
|
|
|
|
|
project_data = pd.DataFrame(self.mock_projects)
|
|
|
|
|
|
self.assertTrue(len(project_data) > 0)
|
|
self.assertIn('name', project_data.columns)
|
|
self.assertIn('client', project_data.columns)
|
|
self.assertIn('status', project_data.columns)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main() |