-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_complete_system.py
More file actions
261 lines (215 loc) Β· 10.5 KB
/
test_complete_system.py
File metadata and controls
261 lines (215 loc) Β· 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/usr/bin/env python3
"""
Comprehensive end-to-end test suite for the appointment management system.
"""
import asyncio
import sys
import os
from datetime import datetime, timedelta
# Add the project root to the sys.path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.db import SessionLocal
from app.models import Owner, Service, Client, Appointment, AppointmentStatus
from app.routes.client import handle_client_message
from app.services.test_messaging import enable_test_mode, get_captured_messages, clear_captured_messages
from app.utils.session import clear_session
class SystemTester:
"""Comprehensive system testing class."""
def __init__(self):
self.db = SessionLocal()
self.test_phone = "+1234567890"
self.test_results = []
async def run_all_tests(self):
"""Run all system tests."""
print("π§ͺ **COMPREHENSIVE SYSTEM TEST SUITE**")
print("=" * 60)
# Enable test mode
enable_test_mode()
# Run test categories
await self.test_booking_flow()
await self.test_appointment_management()
await self.test_natural_language()
await self.test_background_jobs()
await self.test_error_handling()
await self.test_owner_dashboard()
# Print summary
self.print_test_summary()
async def test_booking_flow(self):
"""Test complete booking flow."""
print("\nπ
**TEST 1: Complete Booking Flow**")
print("-" * 40)
# Clear any existing session
clear_session(self.test_phone)
clear_captured_messages(self.test_phone)
# Test booking flow steps
steps = [
("book", "Start booking"),
("Test User", "Provide name"),
("1", "Select service"),
("2", "Select tomorrow"),
("1", "Select time slot")
]
for message, description in steps:
print(f" π {description}: '{message}'")
await handle_client_message(self.test_phone, message, self.db)
captured = get_captured_messages(self.test_phone)
if captured:
print(f" β
Response: {captured[-1]['content'][:50]}...")
else:
print(f" β No response")
# Check if appointment was created
appointment = self.db.query(Appointment).filter(
Appointment.client_id == self.db.query(Client).filter(Client.phone == self.test_phone).first().id
).order_by(Appointment.id.desc()).first()
if appointment:
print(f" β
Appointment created: ID {appointment.id}")
self.test_results.append(("Booking Flow", "PASS"))
else:
print(f" β No appointment created")
self.test_results.append(("Booking Flow", "FAIL"))
async def test_appointment_management(self):
"""Test appointment management (view, cancel, reschedule)."""
print("\nπ **TEST 2: Appointment Management**")
print("-" * 40)
# Test viewing appointments
clear_captured_messages(self.test_phone)
await handle_client_message(self.test_phone, "appointments", self.db)
captured = get_captured_messages(self.test_phone)
if captured and "appointments" in captured[-1]['content'].lower():
print(f" β
View appointments: Working")
self.test_results.append(("View Appointments", "PASS"))
else:
print(f" β View appointments: Failed")
self.test_results.append(("View Appointments", "FAIL"))
# Test cancel flow
clear_captured_messages(self.test_phone)
await handle_client_message(self.test_phone, "cancel", self.db)
captured = get_captured_messages(self.test_phone)
if captured and "cancel" in captured[-1]['content'].lower():
print(f" β
Cancel flow: Working")
self.test_results.append(("Cancel Flow", "PASS"))
else:
print(f" β Cancel flow: Failed")
self.test_results.append(("Cancel Flow", "FAIL"))
async def test_natural_language(self):
"""Test natural language command recognition."""
print("\nπ£οΈ **TEST 3: Natural Language Commands**")
print("-" * 40)
natural_commands = [
("Hi! Can you show me my appointments?", "appointments"),
("I'd like to book a haircut", "booking"),
("I need to cancel my appointment", "cancel"),
("Can I reschedule?", "reschedule")
]
for command, expected_action in natural_commands:
clear_captured_messages(self.test_phone)
await handle_client_message(self.test_phone, command, self.db)
captured = get_captured_messages(self.test_phone)
if captured and expected_action in captured[-1]['content'].lower():
print(f" β
'{command}' β {expected_action}")
self.test_results.append((f"Natural Language: {expected_action}", "PASS"))
else:
print(f" β '{command}' β Failed")
self.test_results.append((f"Natural Language: {expected_action}", "FAIL"))
async def test_background_jobs(self):
"""Test background job system."""
print("\nβ° **TEST 4: Background Jobs**")
print("-" * 40)
try:
from app.services.background_jobs import send_appointment_reminder
# Get a test appointment
appointment = self.db.query(Appointment).filter(
Appointment.status == AppointmentStatus.CONFIRMED
).first()
if appointment:
clear_captured_messages(appointment.client.phone)
await send_appointment_reminder(appointment.id, '24h')
captured = get_captured_messages(appointment.client.phone)
if captured and "reminder" in captured[-1]['content'].lower():
print(f" β
Appointment reminders: Working")
self.test_results.append(("Background Jobs", "PASS"))
else:
print(f" β Appointment reminders: Failed")
self.test_results.append(("Background Jobs", "FAIL"))
else:
print(f" β οΈ No confirmed appointments for testing")
self.test_results.append(("Background Jobs", "SKIP"))
except Exception as e:
print(f" β Background jobs test failed: {e}")
self.test_results.append(("Background Jobs", "FAIL"))
async def test_error_handling(self):
"""Test error handling and edge cases."""
print("\nβ οΈ **TEST 5: Error Handling**")
print("-" * 40)
# Test invalid commands
clear_captured_messages(self.test_phone)
await handle_client_message(self.test_phone, "invalid_command_123", self.db)
captured = get_captured_messages(self.test_phone)
if captured and ("help" in captured[-1]['content'].lower() or "command" in captured[-1]['content'].lower()):
print(f" β
Invalid command handling: Working")
self.test_results.append(("Error Handling", "PASS"))
else:
print(f" β Invalid command handling: Failed")
self.test_results.append(("Error Handling", "FAIL"))
async def test_owner_dashboard(self):
"""Test owner dashboard functionality."""
print("\nπ¨βπΌ **TEST 6: Owner Dashboard**")
print("-" * 40)
try:
# Test dashboard data retrieval
owner = self.db.query(Owner).first()
if owner:
from app.services.optimizer import get_optimization_suggestions
today = datetime.now().date()
suggestions = await get_optimization_suggestions(self.db, owner.id, today)
if suggestions.get('success'):
print(f" β
Dashboard data: Working")
print(f" - Suggestions: {suggestions.get('total_suggestions', 0)}")
self.test_results.append(("Owner Dashboard", "PASS"))
else:
print(f" β Dashboard data: Failed")
self.test_results.append(("Owner Dashboard", "FAIL"))
else:
print(f" β οΈ No owner found for testing")
self.test_results.append(("Owner Dashboard", "SKIP"))
except Exception as e:
print(f" β Dashboard test failed: {e}")
self.test_results.append(("Owner Dashboard", "FAIL"))
def print_test_summary(self):
"""Print test results summary."""
print("\n" + "=" * 60)
print("π **TEST RESULTS SUMMARY**")
print("=" * 60)
passed = len([r for r in self.test_results if r[1] == "PASS"])
failed = len([r for r in self.test_results if r[1] == "FAIL"])
skipped = len([r for r in self.test_results if r[1] == "SKIP"])
total = len(self.test_results)
print(f"β
Passed: {passed}/{total}")
print(f"β Failed: {failed}/{total}")
print(f"βοΈ Skipped: {skipped}/{total}")
print(f"\nπ **Detailed Results:**")
for test_name, result in self.test_results:
status_emoji = "β
" if result == "PASS" else "β" if result == "FAIL" else "βοΈ"
print(f" {status_emoji} {test_name}: {result}")
if failed == 0:
print(f"\nπ **ALL TESTS PASSED!** The system is ready for production!")
else:
print(f"\nβ οΈ **{failed} tests failed.** Please review and fix issues.")
print(f"\nπ‘ **Next Steps:**")
print(f" 1. Start the background worker: python worker.py")
print(f" 2. Access the web interface: http://localhost:8000")
print(f" 3. Test with real WhatsApp: Configure Twilio credentials")
print(f" 4. Deploy to production: Set up production environment")
async def main():
"""Run the complete test suite."""
tester = SystemTester()
try:
await tester.run_all_tests()
except Exception as e:
print(f"β Test suite failed: {e}")
import traceback
traceback.print_exc()
finally:
tester.db.close()
if __name__ == "__main__":
asyncio.run(main())