youssefreda9 commited on
Commit
9416b5d
·
1 Parent(s): 3e99551

test: comprehensive Quran test suite - 55 tests all passing

Browse files
Files changed (1) hide show
  1. test_quran.py +276 -0
test_quran.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Comprehensive test suite for Quran search feature (quran.py)
5
+ Tests edge cases, boundary conditions, and data integrity.
6
+ """
7
+
8
+ import sys
9
+ import os
10
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
11
+ from quran import search_bayan, normalize_arabic
12
+ import sqlite3
13
+ import re
14
+
15
+ DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'quran_master.db')
16
+
17
+ passed = 0
18
+ failed = 0
19
+ errors = []
20
+
21
+ def test(name, condition, detail=""):
22
+ global passed, failed, errors
23
+ if condition:
24
+ passed += 1
25
+ print(f" ✅ {name}")
26
+ else:
27
+ failed += 1
28
+ errors.append((name, detail))
29
+ print(f" ❌ {name} — {detail}")
30
+
31
+ def get_result(query, lang="تدقيق الايات"):
32
+ return search_bayan(query, lang, db_path=DB_PATH)
33
+
34
+ # ══════════════════════════════════════════
35
+ print("\n🔤 1. الحروف المقطعة (Huruf Muqatta'at)")
36
+ print("=" * 50)
37
+
38
+ # الم - البقرة
39
+ r = get_result("الم ذلك الكتاب لا ريب فيه")
40
+ test("الم موجودة في البقرة", "الٓمٓ" in r.get("matched_segment", "") or "الم" in r.get("matched_segment", ""))
41
+
42
+ # الر - يوسف
43
+ r = get_result("الر تلك آيات الكتاب المبين")
44
+ test("الر موجودة في يوسف", "الٓر" in r.get("matched_segment", "") or "الر" in r.get("matched_segment", ""))
45
+
46
+ # حم - غافر
47
+ r = get_result("حم تنزيل الكتاب من الله")
48
+ test("حم موجودة", "حمٓ" in r.get("matched_segment", "") or "حم" in r.get("matched_segment", ""))
49
+
50
+ # كهيعص - مريم
51
+ r = get_result("كهيعص ذكر رحمة ربك عبده زكريا")
52
+ seg = r.get("matched_segment", "")
53
+ test("كهيعص موجودة", "كٓهيعٓصٓ" in seg or "كهيعص" in seg or "مريم" in seg.lower() or "مَرْيَمَ" in seg)
54
+
55
+ # طه
56
+ r = get_result("طه ما انزلنا عليك القرآن لتشقى")
57
+ test("طه موجودة", "طه" in r.get("matched_segment", "") or "طٰهٰ" in r.get("matched_segment", ""))
58
+
59
+ # يس
60
+ r = get_result("يس والقرآن الحكيم")
61
+ test("يس موجودة", "يسٓ" in r.get("matched_segment", "") or "يس" in r.get("matched_segment", ""))
62
+
63
+ # ══════════════════════════════════════════
64
+ print("\n📖 2. البسملة")
65
+ print("=" * 50)
66
+
67
+ # الفاتحة - need unique verses (بسملة alone matches many surahs)
68
+ r = get_result("الحمد لله رب العالمين الرحمن الرحيم مالك يوم الدين")
69
+ seg = r.get("matched_segment", "")
70
+ ref_match = re.search(r'【([^】]+)】', seg)
71
+ ref = ref_match.group(1) if ref_match else ""
72
+ test("الفاتحة: آيات ٢-٤", "لْحَمْدُ" in seg and "(٤)" in seg, f"seg={seg[:80]}")
73
+ test("الفاتحة: اسم السورة", "الفاتحة" in ref, f"ref={ref}")
74
+
75
+ # سورة عادية - البسملة لازم تتشال
76
+ r = get_result("الر تلك آيات الكتاب المبين")
77
+ test("يوسف: البسملة مش موجودة", "بِسْمِ" not in r.get("matched_segment", ""))
78
+
79
+ # التوبة - مفيهاش بسملة أصلاً
80
+ r = get_result("براءة من الله ورسوله")
81
+ seg = r.get("matched_segment", "")
82
+ test("التوبة: مفيش بسملة", "بِسْمِ" not in seg)
83
+ test("التوبة: اسم السورة صح", "التوبة" in seg or "توب" in seg.lower() or "بَرَآءَةٌ" in seg)
84
+
85
+ # النمل 30 - البسملة جزء من الآية
86
+ r = get_result("انه من سليمان وانه بسم الله الرحمن الرحيم")
87
+ seg = r.get("matched_segment", "")
88
+ test("النمل ٣٠: البسملة موجودة (جزء من الآية)", "بِسْمِ" in seg or "سُلَيْمَـٰنَ" in seg)
89
+
90
+ # ══════════════════════════════════════════
91
+ print("\n🔢 3. ترقيم الآيات والمراجع")
92
+ print("=" * 50)
93
+
94
+ # آية واحدة - رقم مفرد
95
+ r = get_result("قل هو الله أحد")
96
+ seg = r.get("matched_segment", "")
97
+ ref_match = re.search(r'【([^】]+)】', seg)
98
+ ref = ref_match.group(1) if ref_match else ""
99
+ test("آية واحدة: مرجع مفرد", ":" in ref and "-" not in ref, f"ref={ref}")
100
+
101
+ # كذا آية - نطاق
102
+ r = get_result("انا انزلناه في ليلة القدر وما ادراك ما ليلة القدر ليلة القدر خير من الف شهر")
103
+ seg = r.get("matched_segment", "")
104
+ ref_match = re.search(r'【([^】]+)】', seg)
105
+ ref = ref_match.group(1) if ref_match else ""
106
+ test("كذا آية: نطاق (من-إلى)", "-" in ref, f"ref={ref}")
107
+
108
+ # أرقام عربية في العثماني
109
+ r = get_result("قل هو الله أحد", "تدقيق الايات")
110
+ seg = r.get("matched_segment", "")
111
+ test("عثماني: أرقام عربية", any(c in seg for c in "٠١��٣٤٥٦٧٨٩"), f"seg={seg[:60]}")
112
+
113
+ # أرقام لاتينية في الإنجليزي
114
+ r = get_result("قل هو الله أحد", "english")
115
+ seg = r.get("matched_segment", "")
116
+ test("إنجليزي: أرقام لاتينية", any(c in seg for c in "0123456789"), f"seg={seg[:60]}")
117
+
118
+ # ══════════════════════════════════════════
119
+ print("\n🚧 4. حدود السور")
120
+ print("=" * 50)
121
+
122
+ # سورة قصيرة كاملة (الإخلاص)
123
+ r = get_result("قل هو الله أحد الله الصمد لم يلد ولم يولد ولم يكن له كفوا أحد")
124
+ seg = r.get("matched_segment", "")
125
+ test("الإخلاص كاملة: ٤ آيات", "(٤)" in seg or "(٤)" in seg.replace("٤","4"))
126
+ test("الإخلاص: مفيش آيات من الفلق", "فَلَقِ" not in seg and "الفلق" not in seg)
127
+
128
+ # سورة القدر - مش يكمل للبينة
129
+ r = get_result("انا انزلناه في ليلة القدر وما ادراك ما ليلة القدر ليلة القدر خير من الف شهر تنزل فيها الملائكة والروح فيها باذن ربهم من كل امر سلام هي حتى مطلع الفجر")
130
+ seg = r.get("matched_segment", "")
131
+ test("القدر: مفيش آيات من البينة", "ٱلْبَيِّنَةُ" not in seg and "بَيِّنَة" not in seg)
132
+ test("القدر: ٥ آيات", "(٥)" in seg or "(٥)" in seg.replace("٥","5"))
133
+
134
+ # الكوثر (أقصر سورة - 3 آيات)
135
+ r = get_result("انا اعطيناك الكوثر فصل لربك وانحر ان شانئك هو الابتر")
136
+ seg = r.get("matched_segment", "")
137
+ test("الكوثر: ٣ آيات كاملة", "(٣)" in seg or "(٣)" in seg.replace("٣","3"))
138
+ ref_match = re.search(r'【([^】]+)】', seg)
139
+ ref = ref_match.group(1) if ref_match else ""
140
+ test("الكوثر: اسم السورة صح", "الكوثر" in ref, f"ref={ref}")
141
+
142
+ # ══════════════════════════════════════════
143
+ print("\n🔤 5. التراجم")
144
+ print("=" * 50)
145
+
146
+ languages = ["english", "french", "turkish", "russian", "spanish", "german", "indonesian", "persian"]
147
+ for lang in languages:
148
+ r = get_result("قل هو الله أحد", lang)
149
+ seg = r.get("matched_segment", "")
150
+ has_content = len(seg) > 10 and "error" not in r
151
+ ref_match = re.search(r'【([^】]+)】', seg)
152
+ ref = ref_match.group(1) if ref_match else ""
153
+ test(f"{lang}: ترجمة + مرجع موجود", has_content and len(ref) > 0, f"ref={ref}, len={len(seg)}")
154
+
155
+ # English with [O Muhammad] — brackets shouldn't break ref
156
+ r = get_result("قل لعبادي الذين آمنوا يقيموا الصلاة", "english")
157
+ seg = r.get("matched_segment", "")
158
+ ref_match = re.search(r'【([^】]+)】', seg)
159
+ ref = ref_match.group(1) if ref_match else ""
160
+ test("English [O Muhammad]: مرجع صح", "Ibrahim" in ref or "إبراهيم" in ref or "braham" in ref.lower(), f"ref={ref}")
161
+
162
+ # English with [in orbit]
163
+ r = get_result("وسخر لكم الشمس والقمر دائبين", "english")
164
+ seg = r.get("matched_segment", "")
165
+ ref_match = re.search(r'【([^】]+)】', seg)
166
+ ref = ref_match.group(1) if ref_match else ""
167
+ test("English [in orbit]: مرجع مش متأثر", len(ref) > 0, f"ref={ref}")
168
+
169
+ # ══════════════════════════════════════════
170
+ print("\n⚠️ 6. حالات خاصة وأخطاء")
171
+ print("=" * 50)
172
+
173
+ # نص فارغ
174
+ r = get_result("")
175
+ test("نص فارغ: رسالة خطأ", "error" in r, f"result={r}")
176
+
177
+ # نص مش عربي
178
+ r = get_result("hello world this is english text")
179
+ seg = r.get("matched_segment", "")
180
+ test("نص إنجليزي: مش بيكسر", True) # should not crash
181
+
182
+ # كلمة واحدة بس
183
+ r = get_result("الله")
184
+ seg = r.get("matched_segment", "")
185
+ test("كلمة واحدة: بيرجع نتيجة", len(seg) > 5, f"seg={seg[:40]}")
186
+
187
+ # كلمتين
188
+ r = get_result("قل هو")
189
+ seg = r.get("matched_segment", "")
190
+ test("كلمتين: بيرجع نتيجة", len(seg) > 5, f"seg={seg[:40]}")
191
+
192
+ # أخطاء إملائية كتير
193
+ r = get_result("انا انزلنه في ليله الكدر")
194
+ seg = r.get("matched_segment", "")
195
+ test("أخطاء إملائية: بيلاقي القدر", "ٱلْقَدْرِ" in seg or "القدر" in seg, f"seg={seg[:60]}")
196
+
197
+ # ══════════════════════════════════════════
198
+ print("\n📊 7. سلامة البيانات")
199
+ print("=" * 50)
200
+
201
+ conn = sqlite3.connect(DB_PATH)
202
+ c = conn.cursor()
203
+
204
+ # عدد الآيات
205
+ c.execute("SELECT COUNT(*) FROM verses")
206
+ total_verses = c.fetchone()[0]
207
+ test(f"إجمالي الآيات: {total_verses}", total_verses >= 6236, f"count={total_verses}")
208
+
209
+ # عدد السور
210
+ c.execute("SELECT COUNT(DISTINCT sura_num) FROM verses")
211
+ total_suras = c.fetchone()[0]
212
+ test(f"إجمالي السور: {total_suras}", total_suras == 114, f"count={total_suras}")
213
+
214
+ # كل سورة ليها اسم مترجم
215
+ c.execute("SELECT COUNT(*) FROM suras_translated")
216
+ trans_count = c.fetchone()[0]
217
+ test(f"أسماء السور المترجمة: {trans_count}", trans_count >= 114, f"count={trans_count}")
218
+
219
+ # أول وآخر آية في القرآن
220
+ c.execute("SELECT text_uthmani FROM verses WHERE sura_num=1 AND aya_num=1")
221
+ first = c.fetchone()[0]
222
+ test("أول آية (الفاتحة ١): موجودة", len(first) > 5)
223
+
224
+ c.execute("SELECT text_uthmani FROM verses WHERE sura_num=114 AND aya_num=6")
225
+ row = c.fetchone()
226
+ test("آخر آية (الناس ٦): موجودة", row is not None and len(row[0]) > 5)
227
+
228
+ # التراجم موجودة
229
+ c.execute("PRAGMA table_info(verses)")
230
+ cols = [row[1] for row in c.fetchall()]
231
+ expected_langs = ["lang_en", "lang_fr", "lang_tr", "lang_ru", "lang_es", "lang_de", "lang_id", "lang_fa"]
232
+ for lang_col in expected_langs:
233
+ test(f"عمود {lang_col} موجود", lang_col in cols, f"cols={cols}")
234
+
235
+ # أطول آية (البقرة 282)
236
+ c.execute("SELECT LENGTH(text_uthmani) FROM verses WHERE sura_num=2 AND aya_num=282")
237
+ longest = c.fetchone()
238
+ test("أطول آية (البقرة ٢٨٢): موجودة", longest is not None and longest[0] > 100, f"len={longest[0] if longest else 0}")
239
+
240
+ # text_clean موجود لكل الآيات
241
+ c.execute("SELECT COUNT(*) FROM verses WHERE text_clean IS NULL OR text_clean = ''")
242
+ empty_clean = c.fetchone()[0]
243
+ test("text_clean مش فاضي لأي آية", empty_clean == 0, f"empty={empty_clean}")
244
+
245
+ conn.close()
246
+
247
+ # ══════════════════════════════════════════
248
+ print("\n🔍 8. أول وآخر القرآن")
249
+ print("=" * 50)
250
+
251
+ # أول آية
252
+ r = get_result("الحمد لله رب العالمين")
253
+ seg = r.get("matched_segment", "")
254
+ test("الفاتحة ٢: نتيجة صحيحة", "ٱلْحَمْدُ" in seg or "الحمد" in seg)
255
+
256
+ # آخر سورة
257
+ r = get_result("قل اعوذ برب الناس ملك الناس اله الناس")
258
+ seg = r.get("matched_segment", "")
259
+ ref_match = re.search(r'【([^】]+)】', seg)
260
+ ref = ref_match.group(1) if ref_match else ""
261
+ test("الناس: اسم السورة صح", "الناس" in ref or "الن" in ref, f"ref={ref}")
262
+
263
+ # أطول آية (البقرة 282)
264
+ r = get_result("يا ايها الذين آمنوا اذا تداينتم بدين الى اجل مسمى فاكتبوه")
265
+ seg = r.get("matched_segment", "")
266
+ test("البقرة ٢٨٢ (أطول آية): بترجع كاملة", len(seg) > 200, f"len={len(seg)}")
267
+
268
+ # ══════════════════════════════════════════
269
+ print("\n" + "=" * 60)
270
+ print(f"📊 النتيجة: {passed} ✅ نجح | {failed} ❌ فشل | من {passed + failed} اختبار")
271
+ print("=" * 60)
272
+
273
+ if errors:
274
+ print("\n❌ الاختبارات الفاشلة:")
275
+ for name, detail in errors:
276
+ print(f" • {name}: {detail}")