الاختبار الساكن
الاختبار الساكن (Static testing) هو تقييم مخرجات العمل (Work products) — المتطلبات وقصص المستخدم والتصاميم وعقود API والكود والإعدادات وخطط الاختبار وحالاته — على يد الأشخاص وبواسطة الأدوات، دون تشغيل البرنامج قيد الاختبار. هذا التعريف صحيح لكنه يبخس الممارسة حقها. فقيمة الاختبار الساكن ليست في غياب التشغيل، بل فيما يتيحه ذلك: أن تفحص متطلباً قبل كتابة أي كود، وأن تصل إلى العيب نفسه لا إلى عَرَض من أعراضه، وأن تتحقق من خصائص مثل الاتساق وقابلية الصيانة لا يقيسها أي اختبار أثناء التشغيل.
هذه الصفحة خريطة الممارسة: الاختبار الساكن مقابل الديناميكي، وما تكتشفه المراجعات وما يكتشفه التحليل الساكن، وأهم أنواع المراجعات، وأصناف الأدوات ونقاطها العمياء، وموقع الفحوص الساكنة في خط CI. أما تصنيف المراجعات ومراجعة المتطلبات فلكلٍّ منهما صفحة تفصيلية ضمن هذا الموضوع.
ما هو الاختبار الساكن — أبعد من «عدم تشغيل الكود»
يخصص منهج ISTQB للمستوى التأسيسي (CTFL v4.0) فصله الثالث للاختبار الساكن ويقسمه إلى عائلتين: المراجعات (Reviews)، وفيها يفحص أشخاص أحد مخرجات العمل، والتحليل الساكن (Static analysis)، وفيه تقيّم الأدوات ذلك المُخرَج وفق قواعد رسمية. وللعائلتين الأهداف نفسها: اكتشاف العيوب مباشرةً في مُخرَج العمل، وتقييم جودته وبناء الثقة به، وإيجاد فهم مشترك بين من كتبوه ومن سيبنون ويختبرون ويشغّلون استناداً إليه.
أهم تمييز هنا هو الفرق بين العيب (Defect) والإخفاق (Failure). العيب خلل في مُخرَج العمل — جملة متناقضة، أو قيمة null غير معالجة، أو استجابة خطأ مفقودة في عقد API. أما الإخفاق فهو ما يفعله النظام خطأً أثناء التشغيل بسبب عيب. يرصد الاختبار الديناميكي الإخفاقات، ثم يتتبع أحدهم العيب بالتنقيح (Debugging) رجوعاً. أما الاختبار الساكن فيصل إلى العيب مباشرةً، وغالباً بموقعه الدقيق. لذلك يكون إصلاح ما يكتشفه الاختبار الساكن أرخص عادةً: لا شيء يُعاد إنتاجه، ولا شيء يُشخَّص، وكثيراً لا يوجد كود يُعاد كتابته بعد.
كل ما يستطيع الإنسان قراءته وفهمه يمكن مراجعته، حتى الوثائق التي لن تُشغَّل أبداً؛ وكل ما له بنية رسمية — كود أو مخطط بيانات (Schema) أو نموذج أو ملف إعدادات — يمكن أيضاً تحليله بأداة.
- ليس تدقيقاً لغوياً. تصحيح الإملاء نتيجة جانبية؛ والهدف هو العيوب التي كانت ستتحول إلى سلوك خاطئ أو إعادة عمل أو مخاطرة.
- ليس بديلاً عن الاختبار الديناميكي. لا يستطيع أن يثبت أن النظام سريع، أو أن الخدمات تتكامل، أو أن المستخدم يستطيع إنجاز مهمته.
- ليس نشاطاً خاصاً بالمطورين. المختبرون يراجعون المتطلبات ووثائق الاختبار، ومالكو المنتج والمصممون يراجع كلٌّ منهم عمل الآخر، ومهندسو العمليات يراجعون إعدادات النشر.
الاختبار الساكن مقابل الاختبار الديناميكي
النوعان متكاملان لا بديلان. تنطلق الفروق أدناه من المقارنة الواردة في منهج ISTQB؛ ومعظم الفرق تحتاج إلى الاثنين في كل مستوى اختبار.
الاختبار الساكن
- 1عيب في مُخرَج عملمتطلب أو تصميم أو عقد API أو كود أو إعدادات أو وثيقة اختبار
- 2يراجعه أشخاص أو تحلّله أدواتالمراجعات: كل ما يُقرأ ويُفهم. التحليل الساكن: كل ما له بنية رسمية
- 3اكتشاف العيب مباشرةًغالباً بموقعه الدقيق؛ لا شيء يُعاد إنتاجه أو يُشخَّص
- متى يمكن أن يبدأ:
- بمجرد وجود مُخرَج عمل، حتى قبل أي كود
- كلفة الاكتشاف:
- أقل عادةً: الموقع معروف وما بُني فوق العيب أقل
الاختبار الديناميكي
- 1تُشغِّل الاختبارات البرنامج
- 2يُرصد إخفاقما يفعله النظام خطأً أثناء التشغيل بسبب عيب
- 3التنقيحإعادة الإنتاج والتشخيص والتتبع رجوعاً
- 4الوصول إلى العيب
- متى يمكن أن يبدأ:
- عند وجود شيء قابل للتشغيل
- كلفة الاكتشاف:
- أعلى: تشمل إعادة الإنتاج والتشخيص وإعادة العمل على ما بُني فوق العيب
- ما الذي يكتشفه — الساكن: العيوب مباشرةً في مُخرَج العمل. الديناميكي (Dynamic testing): الإخفاقات، ومنها تُتتبَّع العيوب بالتنقيح.
- متى يمكن أن يبدأ — الساكن: بمجرد وجود مُخرَج عمل، حتى قبل أي كود. الديناميكي: عند وجود شيء قابل للتشغيل.
- ما الذي يمكنه فحصه — الساكن: المخرجات القابلة للتشغيل وغير القابلة (المتطلبات والتصاميم وخطط الاختبار والعقود). الديناميكي: البرنامج أثناء تشغيله فقط.
- خصائص الجودة — الساكن: الخصائص التي لا تعتمد على التشغيل مثل قابلية الصيانة والاتساق والالتزام بالمعايير. الديناميكي: الخصائص التي تعتمد عليه مثل كفاءة الأداء والموثوقية تحت الحمل وسلوك التكامل الحقيقي.
- العيوب الأسهل اكتشافاً — الساكن: المتطلبات الغامضة أو المتناقضة، والكود غير القابل للوصول أو المكرر، والمتغيرات غير المعرّفة أو غير المهيأة، وعدم تطابق معاملات الواجهات، والانحراف عن معايير الكتابة، وبعض نقاط الضعف الأمنية، ومعايير القبول التي لا يغطيها أي اختبار. الديناميكي: المخرجات الخاطئة لبيانات معينة، وإخفاقات التوقيت والتزامن، ومشكلات البيئة والإعدادات، ومشكلات قابلية الاستخدام.
- كلفة الاكتشاف — الساكن: أقل عادةً، لأن الموقع معروف وما بُني فوق العيب أقل. الديناميكي: أعلى، لأنها تشمل إعادة الإنتاج والتشخيص وإعادة العمل على ما بُني فوق العيب.
ما الذي يمكن اختباره ساكناً، وما الذي يكتشفه عادةً
مثال: تقول قصة مستخدم «يُطبَّق الخصم على الطلبات التي تزيد على 500 ريال». يسأل المراجع: هل يستحق الطلب الذي قيمته 500.00 ريال بالضبط الخصم؟ هذا اكتشاف ساكن في جملة واحدة، قبل أي كود. وإن لم يسأل أحد، يختار المطور «أكبر من» أو «أكبر من أو يساوي»، وقد يكشف اختبار القيم الحدّية بعد أسابيع أن اختياره يخالف ما توقعته الإدارة المالية. العيب نفسه، اكتُشف في موضعين، بكلفتين مختلفتين جداً. وتبيّن القائمة أدناه ما يخفيه كل نوع من المخرجات عادةً.
- المتطلبات وقصص المستخدم — الغموض، والتناقضات، والإغفالات (مسارات الخطأ والصلاحيات والحدود)، والعبارات غير القابلة للاختبار، وقواعد العمل المكررة أو المتعارضة.
- المعمارية والتصميم — ضعف التقسيم إلى وحدات، ونقاط الإخفاق المنفردة، وهياكل البيانات أو تصميم قاعدة البيانات غير الكفء، وغياب معالجة الأخطاء بين المكونات، وعدم وضوح ملكية البيانات.
- عقود API ومخططات البيانات — التسمية غير المتسقة، واستجابات الخطأ المفقودة، والأنواع التي تناقض أمثلتها، والتغييرات الكاسرة بين الإصدارات، والحقول بلا قيود.
- الكود المصدري — المتغيرات غير المعرّفة أو غير المستخدمة، والكود غير القابل للوصول أو المكرر، والتعقيد المفرط، والاستدعاءات غير الآمنة، وبناء الاستعلامات من مدخلات المستخدم، ومخالفة معايير الكتابة.
- الإعدادات والبنية التحتية ككود (Infrastructure as code) — أسرار محفوظة كنص صريح، وقيم افتراضية غير آمنة، وقيم خاطئة لبيئة ما، وYAML غير صالح، وجدول cron لا يعمل أبداً.
- وثائق الاختبار — خطة اختبار بلا معايير خروج، وحالات اختبار بنتائج متوقعة مبهمة، ومعايير قبول بلا أي اختبار، وحالات مكررة أو متقادمة.
جرّبها: كاشف غموض المتطلبات بالذكاء الاصطناعي جرّبها: محلّل مخاطر عقود API بالذكاء الاصطناعي
الاكتشاف المبكر للعيوب ومنع العيوب
تُدخَل العيوب عادةً مبكراً وتُكتشف متأخرة. سوء الفهم في متطلب يصبح قراراً في التصميم، ثم كوداً، ثم اختبارات مكتوبة على سوء الفهم نفسه — وكل طبقة بُنيت فوقه يجب إعادة العمل عليها حين يُلاحَظ أخيراً. يقصّر الاختبار الساكن حلقة التغذية الراجعة هذه: يُسأل عن المتطلب يوم كتابته، وعن التصميم قبل برمجته، وعن التغيير قبل دمجه. ويتناول منهج ISTQB التغذية الراجعة المبكرة والمتكررة من أصحاب المصلحة مع عملية المراجعة، ويشير إلى أنها قد تمنع سوء الفهم حول المتطلبات.
الاكتشاف المبكر ومنع العيوب (Defect prevention) مترابطان لكنهما مختلفان. الاكتشاف يجد هذا العيب أسرع؛ والمنع يوقف العيب التالي قبل أن يُرتكب. وتسهم المراجعات في المنع بطريقتين: الأشخاص يتعلمون — فالمطور الذي تتكرر على تغييراته ملاحظة «المدخلات غير متحقق منها» يبدأ بالتحقق منها — والملاحظات تعود إلى العملية بنوداً في قوائم التحقق وقوالب وقواعد كتابة وقواعد linter. ونوع العيب الذي يظهر في عدة مراجعات مرشّح لفحص آلي، كي لا يضطر أي إنسان للبحث عنه مجدداً.
- صنّف ملاحظات المراجعة حسب النوع — غموض، أو غياب معالجة الأخطاء، أو تسمية، أو أمان، أو فجوة اختبار. الأعداد تبيّن من أين تأتي العيوب.
- أصلح القالب لا الوثيقة وحدها: قالب قصة مستخدم فيه عنوان «حالات الخطأ» يزيل فئة كاملة من الإغفالات.
- أشرك المختبرين في جلسات تنقيح القصص. سؤال «كيف سأختبر هذا؟» هو في حد ذاته اختبار ساكن.
المراجعات: الجانب البشري من الاختبار الساكن
المراجعة فحص منظّم لمُخرَج عمل يجريه أشخاص غير مؤلفه أو إضافةً إليه. وتتدرج المراجعات من زميل يقرأ طلب دمج (Pull request) إلى تفتيش رسمي بأدوار مدرَّبة ومعايير دخول ومقاييس تُجمع. يصف CTFL v4.0 أربعة أنواع على هذا المقياس من الرسمية: المراجعة غير الرسمية (Informal review)، والجولة التفقدية (Walkthrough)، والمراجعة الفنية (Technical review)، والتفتيش (Inspection). ويعرّف معيار IEEE 1028-2008 لمراجعات البرمجيات وتدقيقها (المدرج لدى IEEE حالياً كمعيار غير نشط محفوظ) إضافةً إليها مراجعات الإدارة (Management reviews) والتدقيق (Audits)، وهما يقيّمان التقدم والامتثال لا المحتوى الفني للمُخرَج. ويصف المعيار ISO/IEC 20246 إطاراً عاماً لمراجعة مخرجات العمل.
تستند المراجعات إلى عملية عامة واحدة — التخطيط، وبدء المراجعة، والمراجعة الفردية، والتواصل والتحليل، والإصلاح والتقرير — وكلما زادت رسمية المراجعة نُفّذ منها قدر أكبر؛ أما المراجعة غير الرسمية فلا تتبع عملية محددة. والأدوار الرئيسية هي: المدير، والمؤلف، والميسّر (Moderator)، والمدوّن (Scribe)، والمراجع، وقائد المراجعة. وتقارن صفحة أنواع مراجعات البرمجيات بين الأنواع الأربعة من حيث الغرض والرسمية والقائد والأدوار والتوثيق والمقاييس، وتشرح العملية والأدوار وعوامل النجاح بالتفصيل.
- المراجعة غير الرسمية — نظرة ثانية سريعة بلا عملية محددة.
- الجولة التفقدية — يقود المؤلف المشاركين عبر مُخرَج العمل ليشرحه ويصل معهم إلى فهم مشترك.
- المراجعة الفنية — زملاء مؤهلون، بقيادة ميسّر، يتخذون قرارات بشأن مسألة فنية.
- التفتيش — النوع الأكثر رسمية، هدفه اكتشاف أكبر عدد ممكن من العيوب، مع جمع المقاييس.
مراجعات المتطلبات والتصميم والكود ووثائق الاختبار
نوع المراجعة يصف مدى رسميتها؛ أما مُخرَج العمل فيحدد ما يبحث عنه المراجعون. قد يجري الفريق نفسه جولة تفقدية على تصميم، ومراجعة غير رسمية لمعظم تغييرات الكود، وتفتيشاً على قواعد الدفع.
- مراجعات المتطلبات — تفحص الغموض والاكتمال والاتساق والصحة وقابلية الاختبار وقابلية التنفيذ وقابلية التتبع والاحتياجات غير الوظيفية، ويفضَّل أن يشارك فيها المنتج والتطوير والاختبار معاً. هنا يؤتي الاختبار الساكن أكبر ثماره عادةً، ولها صفحة خاصة بقائمة تحقق ومثال عملي.
- مراجعات التصميم — تتحقق من أن التصميم يلبي المتطلبات بما فيها غير الوظيفية: كيف ينتقل الإخفاق بين الخدمات، وأين تعيش البيانات ومن يملكها، وماذا يحدث تحت ذروة الحمل، وكيف سيُختبر النظام ويُراقَب. اسأل عن كل سهم في المخطط: «ماذا يحدث إن كانت هذه التبعية بطيئة أو غير متاحة؟».
- مراجعات الكود (Code review) — تفحص الصحة والاختبارات وقابلية القراءة والأمان والاتساق مع قاعدة الكود. ويضع دليل Google المنشور لمراجعة الكود معياراً عملياً: وافق على التغيير متى حسّن بوضوح الصحة العامة للكود حتى لو لم يكن مثالياً، وميّز الملاحظات الاختيارية (مثلاً بالبادئة «Nit:») كي يعرف المؤلف ما الذي يمنع الدمج. ودع الأدوات تفرض التنسيق والأسلوب لتتجه عناية البشر إلى المنطق والتصميم والاختبارات.
- مراجعات خطة الاختبار — تفحص النطاق وما هو خارجه صراحةً، والمخاطر التي تعالجها الخطة، والنهج في كل مستوى اختبار، ومعايير الدخول والخروج، والبيئات والبيانات، والمسؤوليات والجدول الزمني. الخطة التي بلا معايير خروج لا تستطيع أن تخبر أحداً متى ينتهي الاختبار.
- مراجعات حالات الاختبار — تتحقق من أن كل حالة ترتبط بمتطلب أو معيار قبول، وتذكر شروطها المسبقة وبياناتها، ولها نتيجة متوقعة قابلة للملاحظة، وأن المجموعة تغطي الحالات السلبية والحدّية دون تكرار. أما تشريح حالة الاختبار الجيدة فيشرحه دليل كتابة حالات الاختبار.
جرّبها: مراجع معايير القبول بالذكاء الاصطناعي جرّبها: محسّن حالات الاختبار بالذكاء الاصطناعي جرّبها: كاشف حالات الاختبار المكرّرة بالذكاء الاصطناعي جرّبها: محلّل تغطية الاختبار بالذكاء الاصطناعي
التحليل الساكن: أصناف الأدوات وما تفحصه
التحليل الساكن هو النصف الآلي من الاختبار الساكن: برنامج يقرأ الكود أو نموذجاً أو وثيقة منظمة ويبلّغ عن مخالفات القواعد. يحتاج إلى بنية رسمية — لغة برمجة، أو مخطط بيانات، أو صيغة مواصفة — ويتوسع بطريقة لا يقدر عليها البشر: أداة linter تفحص كل سطر في كل تغيير، في كل مرة، خلال ثوانٍ.
الأسماء أدناه أمثلة معروفة في كل صنف، وليست ترتيباً للأفضلية. الأداة الصحيحة هي التي تدعم لغاتك، وتعمل في خط التسليم لديك، وتنتج إنذارات كاذبة قليلة بما يكفي ليظل الفريق يقرأ مخرجاتها.
- أدوات linter وفحص الأسلوب — تنبّه إلى البنى المريبة ومخالفات الأعراف: متغيرات غير مستخدمة، وكود غير قابل للوصول، وأسماء محجوبة، وawait مفقود، وتنسيق غير متسق. أمثلة: ESLint (JavaScript وTypeScript)، وPylint وRuff (Python)، وCheckstyle (Java)، وRuboCop (Ruby)، وShellCheck (سكربتات shell)، وSQLFluff (SQL).
- مدققات الأنواع والمترجمات (Type checkers) — تتحقق من استخدام القيم بما يتسق مع أنواعها المعلنة، فتلتقط فئات كاملة من أخطاء null والأنواع قبل التشغيل. أمثلة: مترجم TypeScript، وmypy للغة Python، ومترجمات اللغات ذات الأنواع الساكنة مثل Java وC# وGo وRust.
- الاختبار الأمني الساكن للتطبيقات (SAST) — يتتبع البيانات من المصادر غير الموثوقة إلى المواضع الخطرة ويطابق أنماط الضعف المعروفة: حقن SQL، والبرمجة عبر المواقع (XSS)، واجتياز المسارات، والأسرار المكتوبة في الكود، والتشفير الضعيف. أمثلة: Semgrep وCodeQL وSonarQube وSpotBugs مع إضافات الأمان. وتنشر OWASP إرشادات حول ما تستطيعه أدوات تحليل الكود المصدري وما لا تستطيعه، ويحتفظ برنامج SAMATE التابع لـ NIST بمجموعات اختبار لتقييمها.
- التحقق من مخططات البيانات والمواصفات — يتحقق من صلاحية المخرجات المنظمة وفق مواصفاتها: JSON مقابل JSON Schema، ووثيقة OpenAPI مقابل مواصفة OpenAPI، وسلامة بنية XML، وصياغة YAML وcron. وتضيف أدوات فحص OpenAPI مثل Spectral قواعد اتساق وأسلوب فوق الصلاحية البنيوية.
- مقاييس التعقيد وقابلية الصيانة — التعقيد الدوري (Cyclomatic complexity)، وطول الدوال، والتكرار، والاقتران؛ وهي توجّه المراجعين إلى الكود الصعب اختباره وتغييره.
- ماسحات التبعيات والأسرار والبنية التحتية — تفحص التبعيات المعلنة مقابل قواعد بيانات الثغرات، وتبحث في الـ commits عن بيانات الاعتماد، وتفحص ملفات البنية التحتية ككود والحاويات بحثاً عن إعدادات غير آمنة. أمثلة: npm audit وpip-audit، وOWASP Dependency-Check، وgitleaks، وhadolint، وCheckov.
# Illustrative findings from three kinds of static analysis
src/checkout/discount.ts:41:18 error "rate" is possibly "undefined". TS18048 (type checker)
src/checkout/discount.ts:57:3 error Unreachable code. no-unreachable (linter)
src/orders/search.ts:22:9 error SQL query built by concatenating request
parameter "q"; use a parameterised query. sql-injection (SAST)
openapi.yaml paths./orders/{id}.get.responses
warn Operation defines no 4xx response. (contract linter)جرّبها: مدقّق OpenAPI جرّبها: مدقّق JSON Schema جرّبها: مدقّق استعلامات SQL جرّبها: منسّق YAML
ما الذي لا يستطيع التحليل الساكن اكتشافه
التقرير النظيف من التحليل الساكن يعني أن المُخرَج اجتاز القواعد التي كتبها أحدهم. ولا يقول شيئاً عن كون البرنامج يفعل ما يحتاجه مستخدموه.
وكل أداة ترتكب نوعين من الخطأ. الإيجابيات الكاذبة (False positives) — تحذيرات عن كود سليم — تآكل الثقة حتى يتوقف الناس عن قراءة التقرير؛ والسلبيات الكاذبة (False negatives) — عيوب تفوت الأداة — تخلق ثقة زائفة. ومن النتائج الكلاسيكية في نظرية الحوسبة أنه لا توجد أداة تحليل تستطيع الحسم في كل خاصية سلوكية غير بديهية لأي برنامج كان، لذا توازن كل أداة بين نوعي الخطأ. تعامل مع التحليل الساكن كمرشِّح سريع يسبق المراجعات والاختبارات الديناميكية، لا كحكم نهائي.
- صحة السلوك. قد تؤكد الأداة أن الدالة تعيد رقماً، لكنها لا تعرف أن الرقم يجب أن يشمل ضريبة القيمة المضافة.
- المتطلبات المفقودة أو المفهومة خطأً. إن لم تذكر القصة الاسترداد أبداً، فلن تبلّغ أي أداة بغياب الاسترداد.
- سلوك التشغيل والبيئة: أزمنة الاستجابة، والذاكرة تحت الحمل الحقيقي، والمهلات، والتكامل مع الخدمات الحقيقية، واختلافات الإعدادات بين بيئة الاختبار والإنتاج.
- معظم عيوب التزامن والتوقيت، والعيوب التي تعتمد على قيم بيانات معينة لا تُبلغ إلا أثناء التشغيل.
- قابلية الاستخدام، وإمكانية الوصول كما يعيشها من يستخدم لوحة المفاتيح أو قارئ الشاشة. تلتقط أدوات linter بعض مشكلات الترميز، مثل صورة بلا نص بديل، لكنها لا تعرف إن كانت الصفحة قابلة للاستخدام فعلاً.
الاختبار الساكن في خط CI/CD
الفحوص الساكنة أرخص مراحل خط التسليم، لذلك تعمل أولاً ومع كل تغيير.
- في المحرر وفي خطافات ما قبل الـ commit (Pre-commit hooks) — تعطي أدوات التنسيق وlinter وفحص الأنواع ملاحظاتها قبل أن يوجد الـ commit أصلاً.
- مع كل طلب دمج — linter وفحص الأنواع وSAST والتحقق من المخططات والعقود ومسح الأسرار، مع عرض النتائج مباشرةً على الفروق (Diff) كي يراها المراجع البشري.
- كبوابة جودة (Quality gate) — المخالفات الجديدة فوق خطورة متفق عليها تمنع الدمج؛ أما المخالفات القائمة في الكود القديم فتُسجَّل كخط أساس (Baseline) وتُسدَّد تدريجياً بدلاً من إيقاف الجميع من اليوم الأول.
- فحوص المواصفات — تحقق من ملفات OpenAPI وJSON Schema والإعدادات في خط التسليم نفسه الذي يبني الكود المعتمد عليها، كي يُفشل العقدُ المكسور البناءَ الذي أدخله.
# Illustrative stage order (commands are examples, not requirements)
stages:
static-checks:
- format-check # formatter in check mode
- lint # e.g. eslint . --max-warnings=0
- typecheck # e.g. tsc --noEmit
- validate-contracts # OpenAPI and JSON Schema files
- sast # security rules on changed code
- secret-scan
unit-tests: { needs: static-checks }
integration-tests: { needs: unit-tests }خطة عملية للبدء
- أضف أداة تنسيق وأداة linter بمجموعة قواعد صغيرة متفق عليها؛ واجعل البناء يفشل عند المخالفات الجديدة فقط.
- تحقق من كل ملف عقد ومخطط بيانات وإعدادات في خط التسليم.
- اجعل المختبرين جزءاً من تنقيح القصص، وراجع كل قصة وفق قائمة تحقق للمتطلبات قبل دخولها السبرنت.
- اتفقوا على سياسة خفيفة لمراجعة الكود: من يراجع، وما الذي يمنع الدمج، وكم يمكن أن ينتظر التغيير مراجعته.
- احتفظ بالتفتيش الرسمي للمخرجات القليلة التي يكون فيها العيب الفائت مكلفاً: قواعد الدفع والتسعير، والكود الحرج أمنياً، والمتطلبات التنظيمية، وترحيل البيانات.
جرّبها: محلّل فجوات المتطلبات بالذكاء الاصطناعي جرّبها: مراجع معايير القبول بالذكاء الاصطناعي
الأسئلة الشائعة
هل الاختبار الساكن مجرد اختبار دون تشغيل الكود؟
هذا يصف الآلية لا الغاية. يفحص الاختبار الساكن مخرجات العمل — المتطلبات والتصاميم والعقود والكود ووثائق الاختبار — لاكتشاف العيوب مباشرةً وتقييم الجودة وبناء فهم مشترك. ولأن لا شيء يحتاج إلى التشغيل، يمكنه البدء قبل وجود أي كود وفحص وثائق لن تُشغَّل أبداً.
ما الفرق بين التحليل الساكن ومراجعة الكود؟
التحليل الساكن تجريه أدوات وفق قواعد رسمية؛ ومراجعة الكود يجريها أشخاص بحكمهم وخبرتهم. الأدوات سريعة ومتسقة ولا تكلّ في الأنماط التي تعرفها؛ والبشر يكتشفون مشكلات التصميم ومنطق العمل الخاطئ والاختبارات المفقودة والنية غير الواضحة. شغّل الأدوات أولاً كي لا يصرف المراجعون انتباههم على التنسيق والأخطاء البسيطة.
هل يمكن أن يحل الاختبار الساكن محل الاختبار الديناميكي؟
لا. يكتشف الاختبار الساكن العيوب في مخرجات العمل ويفحص خصائص مثل قابلية الصيانة؛ ويرصد الاختبار الديناميكي سلوك البرنامج أثناء التشغيل بما فيه الأداء والتكامل والبيانات الحقيقية. يكتشفان عيوباً مختلفة، والعملية الناضجة تستخدم الاثنين في كل مستوى اختبار.
هل التفتيش هو نفسه المراجعة؟
التفتيش نوع من أنواع المراجعة — أكثرها رسمية. يصف CTFL v4.0 أربعة أنواع: المراجعة غير الرسمية والجولة التفقدية والمراجعة الفنية والتفتيش. ويتبع التفتيش عملية المراجعة كاملة، ويستخدم أدواراً محددة، ويهدف إلى اكتشاف أكبر عدد ممكن من العيوب، ويجمع مقاييس لتحسين العملية.
هل يكفي SAST لأمان التطبيق؟
لا. يكتشف SAST أنماط الضعف على مستوى الكود، لكنه لا يرى إعدادات التشغيل، ولا ثغرات المصادقة والتفويض المرتبطة بقواعد العمل، ولا عمليات النشر المعرّضة للخطر. اجمعه مع مراجعة التصميم وفحص التبعيات والاختبار الأمني الديناميكي، ومع اختبار الاختراق للأنظمة المهمة.
المراجع
- ISTQB Certified Tester Foundation Level (CTFL) v4.0المنهج التأسيسي لاختبار البرمجيات: مستويات الاختبار وأنواعه وتقنيات تصميم الاختبارات وإدارة الاختبار والأدوات.
- ISO/IEC 20246:2017 — Software and systems engineering — Work product reviewsإطار عام لمراجعة مخرجات العمل — عملية المراجعة وأدوارها وتقنياتها.
- IEEE 1028-2008 — IEEE Standard for Software Reviews and Auditsالتعريفات الكلاسيكية لمراجعات الإدارة والمراجعات الفنية والتفتيش والجولات التفقدية والتدقيق (مدرج لدى IEEE كمعيار غير نشط محفوظ).
- ISTQB Glossaryالتعريفات القياسية لمصطلحات الاختبار — حالة الاختبار واختبار الانحدار والخطورة والأولوية وتحليل القيم الحدّية وغيرها.
- Source Code Analysis Toolsما الذي تفعله أدوات الاختبار الأمني الساكن للتطبيقات (SAST)، ونقاط قوتها وضعفها، وكيف تُختار.
- Software Assurance Metrics And Tool Evaluation (SAMATE)برنامج NIST لتقييم أدوات ضمان البرمجيات، ومنها أدوات التحليل الساكن، ومجموعات الاختبار المستخدمة لقياسها.
- Code Review Developer Guideممارسات Google المنشورة لمراجعة الكود: ما الذي يبحث عنه المراجعون، ومعيار الموافقة على التغيير، وكيفية كتابة تعليقات المراجعة.
تمرين عملي
نفّذ اختباراً ساكناً لتغيير في التحويلات المالية قبل دمجه
أنت المختبِر في فريق تطبيق الخدمات المصرفية عبر الجوال لدى بنك للأفراد. تتيح القصة TRF-118 للعملاء تحويل المال إلى مستفيدين محفوظين، وأول طلب دمج (Pull request) جاهز: مقتطف عقد API وكود الخادم في المادة أدناه. وقبل دمج أي شيء أو تشغيله، يراجع الفريق معاً أربعة مخرجات عمل: القصة والعقد والكود وأول حالة اختبار. ودورك هو المراجعة الفردية (Individual review): سجّل كل عيب تجده، وقرّر لكل عيب هل الأرجح أن تبلّغ عنه أداة تحليل ساكن (وسمِّ صنفها: أداة linter، أو مدقق أنواع (Type checker)، أو أداة SAST، أو التحقق من العقود ومخططات البيانات) أم أن المراجع البشري وحده سيجده.
قصة المستخدم TRF-118: «بصفتي عميلاً من الأفراد، أريد تحويل المال إلى مستفيد محفوظ، كي أدفع للآخرين دون زيارة الفرع». معايير القبول — AC1: يكتمل فوراً أي تحويل لا يتجاوز الحد اليومي. AC2: الحد اليومي 10,000 ريال لكل عميل. AC3: شاشة التحويل سهلة الاستخدام. AC4: يُرفض التحويل الذي يتجاوز الحد. AC5: لكل حساب حد يومي خاص به قدره 10,000 ريال.
حالة الاختبار TC-TRF-07، وهي الوحيدة المكتوبة حتى الآن — العنوان: «تحويل ضمن الحد»؛ الخطوات: 1. سجّل الدخول. 2. حوّل مالاً إلى مستفيد؛ النتيجة المتوقعة: «يعمل التحويل بشكل صحيح». خصّص نحو 45 دقيقة. تكفي الورقة والقلم، ويمكن لأداتَي OpenAPI Validator وJSON Schema Validator تأكيد بعض ما تنسبه إلى الأدوات.
# openapi.yaml (excerpt)
openapi: 3.0.3
info: { title: Transfers API, version: 1.4.0 }
paths:
/accounts/{accountId}/transfers:
post:
operationId: createTransfer
summary: Create a transfer to a saved beneficiary
requestBody:
content:
application/json:
schema:
type: object
properties:
beneficiaryId: { type: string }
amount: { type: number, example: "250.00" }
responses:
'201': { description: Transfer created }
// transfers.ts (excerpt, line numbers on the left)
12 export async function createTransfer(req: TransferRequest): Promise<Transfer> {
13 const limit = await getDailyLimit(req.user.id); // number | undefined
14 const sentToday: number = await db.scalar("SELECT SUM(amount) FROM transfers " +
15 "WHERE customer_id = '" + req.query.customer + "'");
16 if (sentToday + req.body.amount < limit) {
17 return saveTransfer(req.body);
18 }
19 throw new LimitExceeded();
20 audit.log('transfer rejected', req.user.id);
21 }- راجع القصة: علّم كل غموض وتناقض وإغفال وعبارة غير قابلة للاختبار، واكتب كلاً منها سؤالاً لمالك المنتج.
- راجع العقد مقابل القصة: معاملات المسار (Path parameters)، والحقول الإلزامية، والقيود، والأمثلة، واستجابات الخطأ. ويمكنك أن تلصق جزء YAML في أداة OpenAPI Validator وتقارن تقريرها بقائمتك.
- راجع الكود سطراً سطراً مقابل القصة والعقد. ودوّن لكل اكتشاف رقم السطر، وهل تلتقطه أداة linter أو مدقق أنواع أو أداة SAST أم المراجع البشري وحده.
- راجع حالة الاختبار: ارتباطها بمعيار قبول، وشروطها المسبقة وبيانات الاختبار، وهل يمكن ملاحظة نتيجتها المتوقعة، والحالات السلبية والحدّية التي تنقص المجموعة. ويمكنك أن تستخرج المبالغ الحدّية بأداة Boundary Value Analysis لعميل حوّل 6,000 ريال اليوم.
- اختر ثلاثة اكتشافات في الكود، وصِف الإخفاق الذي سيسببه كل منها لعميل أو للبنك لو وصل إلى الإنتاج.
- اختم بثلاث إجابات قصيرة: خطران لا يستطيع أي فحص ساكن لهذه الحزمة استبعادهما، مع الاختبار الديناميكي الذي يستطيع ذلك لكل منهما؛ وإجراء واحد لمنع العيوب مع مرحلة خط التسليم التي تنتمي إليها الفحوص القابلة للأتمتة؛ ونوع المراجعة الذي تختاره لهذا التغيير مع السبب.
إظهار الإجابة النموذجية
كل بند أدناه عيب (Defect): خلل في مُخرَج عمل اكتُشف دون تشغيل أي شيء. ولم يصبح أيٌّ منها إخفاقاً (Failure) بعد؛ فالإخفاق هو ما سيعيشه العميل لو وصل العيب إلى نظام قيد التشغيل (الخطوة 5). تسرد الإجابة النموذجية 17 اكتشافاً؛ وقد تختلف صياغتك، وفي آخرها بعض الاكتشافات الصحيحة الأخرى.
القصة 1 — غموض (مراجعة بشرية). قاعدة الحد غير واضحة: هل يعني «اليومي» اليوم التقويمي، وبأي منطقة زمنية، أم آخر 24 ساعة؟ وهل يحدّ كل تحويل على حدة أم مجموع تحويلات اليوم؟ وهل تُحتسب التحويلات المرفوضة أو الملغاة؟
القصة 2 — تناقض (مراجعة بشرية). يجعل AC2 الحد لكل عميل، ويجعله AC5 لكل حساب؛ فالعميل الذي يملك حسابين قد يحوّل 10,000 أو 20,000 ريال في اليوم بحسب المعيار الذي يتبعه المطور. وقد امتد التناقض فعلاً: العقد منظم حسب الحساب (/accounts/{accountId}/transfers)، بينما يجمع الكود التحويلات حسب العميل.
القصة 3 — عبارة غير قابلة للاختبار (مراجعة بشرية). «سهلة الاستخدام» في AC3 بلا معيار يمكن ملاحظته. اسأل عن معناها — مثلاً: تعرض الشاشة المبلغ المتبقي لليوم، وتُظهر كل خطأ بجوار الحقل الذي سببه — أو انقلها إلى متطلب لقابلية الاستخدام يمكن تقييمه.
القصة 4 — إغفالات (مراجعة بشرية). لا توجد حالات خطأ: ماذا يرى العميل عند تجاوز الحد؟ وماذا يحدث عند عدم كفاية الرصيد، أو مبلغ يساوي صفراً أو أقل، أو مبلغ بأكثر من منزلتين عشريتين، أو مستفيد حُذف؟
العقد 1 — خطأ بنيوي (أداة: التحقق من العقود ومخططات البيانات). يستخدم المسار {accountId} دون تعريف معامل مسار باسم accountId، ومواصفة OpenAPI تشترط معامل مسار لكل تعبير في قالب المسار. وتبلّغ عنه أداة OpenAPI Validator كخطأ (أما رسائلها الأخرى عن هذا المقتطف فتلميحات فقط، عن info.description وservers).
العقد 2 — استجابات خطأ مفقودة (أداة إن وُجدت لدى الفريق قاعدة لذلك، وإلا فمراجعة بشرية). الموثَّق هو 201 فقط: لا استجابة 4xx لمبلغ يتجاوز الحد أو مبلغ غير صالح أو مستفيد غير معروف، فلا يعرف التطبيق شكل الخطأ. والتحقق البنيوي يقبل عملية باستجابة نجاح واحدة؛ أما قاعدة في أداة فحص العقود تشترط استجابة 4xx، مثل التي تظهر في المخرجات التوضيحية في الدليل، فستبلّغ عنه.
العقد 3 — قيود مفقودة (مراجعة بشرية، أو قاعدة linter مخصصة). جسم الطلب غير معلَّم بـ required: true، ولا يرد أي من الحقلين في required، وليس للحقل amount حد أدنى؛ فالجسم الفارغ أو المبلغ 0 أو -50 صالح وفق العقد. ولرؤية ذلك، اكتب مخطط الطلب بصيغة JSON وتحقق من { "amount": -50 } مقابله في أداة JSON Schema Validator: تعدّ الأداة المستند صالحاً.
العقد 4 — نوع يناقض مثاله (أداة: أداة فحص عقود تتحقق من الأمثلة مقابل مخططاتها). الحقل amount من النوع number، لكن مثاله "250.00" نص، فتعرض الوثائق وخوادم المحاكاة المبنية على المثال نوعاً خاطئاً. وأداة OpenAPI Validator تفحص البنية لا الأمثلة؛ وللتأكد، تحقق من "250.00" مقابل { "type": "number" } في أداة JSON Schema Validator.
الكود 1 — السطران 13 و16 (أداة: مدقق الأنواع). قد تعيد getDailyLimit القيمة undefined، والسطر 16 يقارن بها دون فحص. ومع فحص الأنواع الصارم (strict) يبلّغ مترجم TypeScript في السطر 16 عن TS18048: 'limit' is possibly 'undefined'.
الكود 2 — السطران 14 و15 (أداة: SAST). يُبنى استعلام SQL بلصق معامل من الطلب، وهذا يسمح بحقن SQL. والإصلاح استعلام ذو معاملات (Parameterised query).
الكود 3 — السطر 15 (مراجعة بشرية). يُؤخذ العميل من req.query.customer، وهي قيمة يستطيع مرسل الطلب تغييرها ولا يعرّفها العقد أصلاً، بدلاً من req.user.id الخاص بالمستخدم الذي سجّل دخوله. تبلّغ أداة SAST عن الحقن في هذا السطر، لكن لا أداة تعرف أي عميل هو الصحيح.
الكود 4 — السطران 14 و15 (مراجعة بشرية). لا يحتوي الاستعلام على شرط للتاريخ، فيجمع كل تحويل أجراه العميل منذ البداية لا تحويلات اليوم. ولا يرى ذلك إلا من يعرف أن المتطلب يقول «يومي».
الكود 5 — السطر 16 (مراجعة بشرية). العامل < يرفض التحويل الذي يجعل مجموع اليوم مساوياً للحد تماماً، مع أن AC1 يسمح بالتحويل الذي «لا يتجاوز الحد اليومي» وAC4 لا يرفض إلا ما يتجاوزه. وبالقراءة الحرفية فإن <= هو الصحيح؛ أكّد ذلك مع مالك المنتج مع أسئلة القصة 1، وسجّل الإجابة في القصة. وسيكشفه اختبار القيم الحدّية لاحقاً كإخفاق، بكلفة أعلى.
الكود 6 — السطر 20 (أداة: linter، مثل قاعدة ESLint المسماة no-unreachable؛ ويبلّغ عنه مترجم TypeScript أيضاً حين تكون قيمة allowUnreachableCode هي false). يأتي استدعاء التدقيق بعد throw، فلا يُنفَّذ أبداً، ولا تُسجَّل التحويلات المرفوضة في سجل التدقيق.
حالة الاختبار 1 — نتيجة متوقعة مبهمة (مراجعة بشرية). لا يمكن ملاحظة «يعمل بشكل صحيح». اكتب ما يمكن فحصه: يُنشأ التحويل بالمبلغ المُدخل، وينقص الرصيد بقدره، ويُحدَّث المتبقي من حد اليوم.
حالة الاختبار 2 — بلا شروط مسبقة ولا بيانات اختبار ولا تتبع (مراجعة بشرية). أي عميل وأي حساب؟ وما الحد المضبوط؟ وكم حُوِّل اليوم؟ وما المبلغ؟ ولا تذكر الحالة أنها تغطي AC1، وسينفذها مختبِران بطريقتين مختلفتين.
حالة الاختبار 3 — فجوات في المجموعة (مراجعة بشرية). لا يوجد إلا المسار السعيد. وينقص: مجموع يبلغ 10,000.00 ريال تماماً، وخطوة واحدة فوقه (10,000.01 ريال)، ورسالة تجاوز الحد، وعميل بلا حد مضبوط، ومبلغ صفري أو سالب، وبعد الإجابة عن الأسئلة: حساب ثانٍ وتحويلات حول منتصف الليل. وبالأداة: لعميل حوّل 6,000.00 ريال اليوم، أدخل amount: number, min=0.01, max=4000 واختر الصيغة الثنائية (2-value BVA)؛ فيجب رفض 0 و4000.01 وقبول 0.01 و4000 (وتضيف الأداة أيضاً قيمة واحدة من منتصف المدى). وتستند هذه النتائج المتوقعة إلى إجابات لم يقدّمها مالك المنتج بعد — أن الحد نفسه مسموح، وأن أصغر مبلغ هو 0.01 ريال — فسجّلها افتراضاتٍ في حالة الاختبار.
الحصيلة: خمسة اكتشافات من النوع الذي تلتقطه الأدوات عادةً (العقد 1 و4، والكود 1 و2 و6)، واثنان يحتاجان إلى قاعدة يضيفها الفريق (العقد 2 و3)، وعشرة تحتاج إلى شخص يعرف المتطلب. لهذا يُعامَل التحليل الساكن كمرشِّح سريع يسبق المراجعات، لا كحكم نهائي.
الإخفاقات (الخطوة 5)، أي ثلاثة مما يلي: العميل الذي لا حد مضبوطاً له تُرفض كل تحويلاته، لأن نتيجة المقارنة < مع undefined هي false دائماً في JavaScript (الكود 1)؛ وحين يبلغ مجموع كل تحويلات العميل السابقة 10,000 ريال يُرفض كل تحويل بعدها (الكود 4)؛ والعميل الذي حوّل 6,000 ريال اليوم لا يستطيع تحويل 4,000 ريال أخرى مع أن AC1 يسمح بذلك (الكود 5)؛ وبتغيير المعامل customer يجعل العميلُ الحدَّ يُفحص على تحويلات شخص آخر فيتجاوز حده (الكود 3)؛ وقد يقرأ أحدهم بيانات في قاعدة البيانات أو يغيّرها عبر الحقن (الكود 2)؛ ولا تترك التحويلات المرفوضة أي أثر في سجل التدقيق (الكود 6).
الاختبار الديناميكي (الخطوة 6)، أي خطرين مما يلي: تحويلان يُرسلان في اللحظة نفسها قد يجتازان الفحص كلاهما قبل حفظ أيٍّ منهما — يستطيع المراجع طرح السؤال، لكن اختباراً بطلبات متوازية وحده يبيّن هل تمنع قاعدة البيانات ذلك؛ وهل تخصم saveTransfer المبلغ من الحساب فعلاً ويصل إلى المستفيد، وهذا يحتاج إلى اختبارات التكامل والنظام؛ وزمن الاستجابة تحت الحمل لعبارة «يكتمل فوراً»، وهذا يحتاج إلى اختبار أداء؛ والسلوك حول منتصف الليل بإعداد المنطقة الزمنية في الإنتاج، بعد تعريف «اليومي»، وهذا يحتاج إلى اختبار نظام بتحويلات قبل منتصف الليل وبعده مباشرةً؛ وهل يجد العملاء الشاشة سهلة الاستخدام فعلاً، وهذا يحتاج إلى اختبار قابلية الاستخدام.
منع العيوب وخط التسليم (الخطوة 6). أصلح القالب لا هذه القصة وحدها: أضف إلى قالب قصة المستخدم عنوان «الحدود وحالات الخطأ» (القيمة، وهل يُسمح بمجموع يساوي الحد تماماً، والفترة والمنطقة الزمنية، ولكل عميل أم لكل حساب، والرسالة عند كل خطأ). وحوّل اكتشافات الأدوات إلى فحوص تعمل مع كل طلب دمج قبل اختبارات الوحدة: linter مع no-unreachable، وفحص الأنواع الصارم، وSAST، والتحقق من العقود بقواعد لمعاملات المسار واستجابات 4xx والأمثلة. والمخالفات الجديدة فوق الخطورة المتفق عليها تمنع الدمج، كبوابة جودة (Quality gate).
نوع المراجعة (الخطوة 6). حد التحويل قاعدة دفع يكون فيها العيب الفائت مكلفاً، لذا يناسبه التفتيش (Inspection) الرسمي — أو على الأقل المراجعة الفنية (Technical review) — أكثر من نظرة غير رسمية على طلب الدمج. وقائمتك من هذه المراجعة الفردية هي مدخل النشاط التالي في عملية المراجعة: التواصل والتحليل.
اكتشافات صحيحة أخرى: عبارة «يكتمل فوراً» في AC1 غير واضحة حين يكون حساب المستفيد في بنك آخر؛ وSUM تعيد NULL حين لا تكون للعميل تحويلات بعد، فلا تكون sentToday دائماً الرقم الذي يعلنه نوعها، ولن يرى ذلك مدقق الأنواع إن كانت db.scalar تعيد قيمة بلا نوع محدد؛ ولا شيء في مقتطف الكود يتحقق من أن beneficiaryId من المستفيدين المحفوظين لدى العميل (اسأل هل تفعل ذلك saveTransfer)؛ ولا يعلن مقتطف العقد أي متطلب أمان لعملية تنقل المال (اسأل هل يعرّفه الملف الكامل).
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.
جزء من مسار تعلم ضمان الجودة
قبل هذا الموضوع
الموضوعات التالية
الأدوات المذكورة في هذا الدليل
اكتشف العبارات الغامضة أو المبهمة أو المتناقضة في المتطلبات واحصل على أسئلة توضيحية من الذكاء الاصطناعي من متقن.
اعثر على المتطلبات المفقودة — معالجة الأخطاء والصلاحيات والظروف الحدّية والاحتياجات غير الوظيفية — باستخدام الذكاء الاصطناعي من متقن.
راجع معايير القبول من حيث قابلية الاختبار والاكتمال والغموض، مع اقتراحات صياغة معاد كتابتها من الذكاء الاصطناعي من متقن.
التحقق من مستندات OpenAPI 3.x وSwagger 2.0 للكشف عن الأخطاء البنيوية ومشكلات أفضل الممارسات.
حلّل عقد OpenAPI بحثاً عن مخاطر التصميم: تسمية غير متسقة، واستجابات خطأ مفقودة، ومصادقة ضعيفة، ومخاطر التغييرات الكاسرة، وفجوات التقسيم إلى صفحات والتحقق.
التحقق من مستند JSON مقابل مخطط JSON Schema (الكلمات المفتاحية الأساسية في draft-07 / 2019-09 / 2020-12).
فحص جمل SQL بحثاً عن مشكلات الصياغة والأقواس غير المتوازنة والسلاسل النصية غير المغلقة والأنماط الخطرة.
حسّن حالات الاختبار الموجودة: خطوات أوضح، ونتائج متوقّعة أدق، وشروط مسبقة مفقودة، وبنية أفضل، باستخدام الذكاء الاصطناعي من متقن.
اعثر على حالات الاختبار المكرّرة والمتداخلة في مجموعة اختبار واحصل على توصيات الدمج من الذكاء الاصطناعي من متقن.
قارن المتطلبات أو قصة مستخدم بحالات الاختبار الموجودة للعثور على المجالات غير المختبَرة، باستخدام الذكاء الاصطناعي من متقن.