قراءة الشيفرة للمختبِرين

قراءة الشيفرة عند المختبِر تعني أن تتابع ما يفعله جزء صغير من الشيفرة بمُدخل واحد: أي القيم يحفظ، وأي القرارات يتخذ، وأي الأسطر تُنفَّذ، وما الذي يُعاد في النهاية. ولا تحتاج لذلك إلى كتابة شيفرة إنتاجية، فبضع لبنات أساسية تغطي معظم منطق الأعمال: المتغيّرات، والمقارنات، والعوامل && و|| و!، وif وswitch، والحلقات، وreturn وthrow.

مثال: if (total > 200) { fee = 0; } تُقرأ «إذا كان الإجمالي أكبر من ⁦200⁩ تصبح الرسوم صفراً». فإذا قال المتطلب «الطلبات بقيمة ⁦200⁩ فأكثر توصيلها مجاني»، اختلفت الشيفرة عن المتطلب عند قيمة واحدة بالضبط هي ⁦200⁩. والمختبِر الذي يقرأ هذا السطر يستطيع أن يصمّم الاختبار الذي يكشف ذلك، أو أن يطرح السؤال قبل تشغيل أي اختبار.

لماذا يهم

تقنيات الصندوق الأسود، مثل تقسيم التكافؤ (Equivalence Partitioning) وتحليل القيم الحدّية (Boundary Value Analysis)، تنطلق من المتطلب، فلا ترى ما تقارنه الشيفرة فعلاً، ولا ترتيب قراراتها، ولا المواضع التي تتوقف فيها مبكراً. أما قراءة الشيفرة فتُظهر القرارات التي تقف خلف الأقسام والحدود التي تختبرها، وتكشف سلوكاً لا يذكره أي متطلب: خصماً إضافياً، أو حالة منسية، أو خطأً يُنهي الدالة.

وهي تغيّر أيضاً طريقة عملك مع المطورين: تستطيع أن تراجع تغييراً بحثاً عن القواعد التي يمسّها، وأن تقرأ اختبار وحدة لترى ما يفحصه حقاً، وأن تذكر في تقرير الخطأ المُدخل والسطر الذي تشك فيه. وتعتمد عليها دروس الصندوق الأبيض التالية: فهي تشرح تغطية التعليمات والفروع والشروط على شيفرة مكتوبة تماماً مثل المقتطفات هنا، ومرقّمة الأسطر بالطريقة نفسها.

القيم والمتغيّرات والعوامل

المتغيّر (variable) اسمٌ لقيمة. تُنشئ const اسماً لا يمكن أن يُعطى قيمة جديدة، وتُنشئ let اسماً يمكن إعطاؤه قيمة جديدة. وللقيم أنواع: الأرقام (200) والنصوص ('SAVE10' أو "SAVE10") والقيم المنطقية (true وfalse) ونوعان من «اللاشيء»: undefined (لم تُضبط قيمته) وnull (فارغ عن قصد). والنص الذي يلي // تعليق (comment): ملاحظة للقارئ لا تُنفَّذ أبداً. اقرأ كل مقتطف، ثم قله بكلمات بسيطة:

  • const rate = 0.15; تُقرأ «النسبة ⁦0.15⁩ وتبقى ⁦0.15⁩».
  • let fee = 15; ثم fee = fee + 10; تُقرأ «تبدأ الرسوم بـ⁦15⁩؛ خذ قيمتها الحالية وأضف ⁦10⁩ واحفظ ⁦25⁩». وعلامة = المفردة إسناد (assignment): تغيّر القيمة ولا تقارن أبداً.
  • const item = { price: 30, qty: 2 }; تُقرأ «item يجمع قيمتين مسمّاتين: السعر ⁦30⁩ والكمية ⁦2⁩»، وitem.price تُقرأ «سعر item». و[30, 20] قائمة (array) من قيمتين، و[] قائمة فارغة، وitems.length عدد القيم في items. ولا تثبّت const إلا الاسم: فالقيم داخل القائمة أو الكائن (object) يمكن أن تتغيّر. وفي العمليات الحسابية تعني * الضرب و/ القسمة: item.price * item.qty تُقرأ «سعر item مضروباً في كميته».
  • total === 200 تُقرأ «هل الإجمالي ⁦200⁩ بالضبط؟» ونتيجتها true أو false، و!== تُقرأ «لا يساوي». أما == المزدوجة فتقارن أيضاً لكنها تحوّل الأنواع أولاً، فتكون نتيجة '200' == 200 هي true بينما نتيجة '200' === 200 هي false.
  • total >= 200 تُقرأ «هل الإجمالي ⁦200⁩ فأكثر؟»، أما total > 200 فتستبعد ⁦200⁩ نفسها. وكثيراً ما تختبئ عيوب الحدود في هذا الحرف الواحد.
  • member && total >= 100 تُقرأ «عضو، والإجمالي ⁦100⁩ على الأقل»: نتيجتها true فقط إذا تحقق الطرفان. وexpress || urgent نتيجتها true إذا تحقق طرف واحد على الأقل. و!express تُقرأ «ليس توصيلاً سريعاً». ويتوقف && عند أول طرف غير متحقق، ويتوقف || عند أول طرف متحقق، فقد لا يُقيَّم الطرف الثاني أبداً.
  • a || b && c تُقرأ a || (b && c)، لأن && يُقيَّم قبل ||. والأقواس تغيّر المعنى، فاقرأها بعناية.
  • if (qty) تستخدم قيمةً بوصفها شرطاً: فالقيم 0 والنص الفارغ وnull وundefined وNaN («ليس رقماً»، وهو ناتج عملية حسابية مثل 0 / 0 أو 5 - undefined) تُعامَل كأنها false. وعندها تُعامَل الكمية ⁦0⁩ معاملة الكمية المفقودة. والقاعدة نفسها تختبئ في qty || 1 التي تُقرأ «qty، أو ⁦1⁩ إذا عُوملت qty كأنها false»: فالعاملان || و&& يعيدان إحدى القيمتين نفسها، لا true أو false فقط، فتصبح الكمية ⁦0⁩ بصمت ⁦1⁩.

القرارات: if وelse وswitch وreturn وthrow

القرار يختار الأسطر التي تُنفَّذ بعده. والأسطر الواقعة بين { و} تشكّل كتلة (block): إما أن يدخلها القرار وإما أن يتجاوزها كلها. والإزاحة (indentation) تساعد العين فقط، أما JavaScript فتتبع الأقواس: فعبارة if بلا أقواس لا تتحكم إلا في العبارة الواحدة التي تليها، مهما كانت إزاحة الأسطر بعدها. لذلك إذا وصلتك شيفرة سيئة الإزاحة أو مضغوطة (minified) في سطر واحد طويل، فأعد إزاحتها قبل أن تتتبّعها. وفي سلسلة if / else if / else تُفحص الشروط من الأعلى، وأول شرط متحقق تُنفَّذ كتلته ويُتجاوز باقي السلسلة، حتى لو كان شرط لاحق متحققاً أيضاً. لذلك فترتيب الشروط جزء من المنطق.

  • if (total <= 0) { … } else if (total < 200) { … } else { … } تُقرأ «صفر أو أقل؛ وإلا فأقل من ⁦200⁩؛ وإلا فكل ما عدا ذلك». تُنفَّذ كتلة واحدة فقط.
  • switch (coupon) { case 'SAVE10': …; break; case 'HALF': …; break; default: … } تُقرأ «قارن القسيمة بكل حالة باستخدام ===، ونفّذ أول حالة تطابقها، أو default إن لم تطابق أي حالة». ومن دون break ينتقل التنفيذ إلى الحالة التالية (fall-through)، وهذا عيب كلاسيكي حين لا يكون مقصوداً.
  • return fee; تُقرأ «توقف هنا وأعد الرسوم إلى المستدعي». ولا يُنفَّذ بعدها شيء في الدالة نفسها، فعبارة return المبكرة في أعلى الدالة تتجاوز كل ما تحتها.
  • throw new Error('Order total must be positive'); تُقرأ «توقف هنا بخطأ». ينتقل الخطأ إلى الشيفرة التي استدعت الدالة، ويمكنها التقاطه بـtry / catch؛ وإن لم يلتقطه شيء توقفت العملية، وتُبلغ وحدة التحكم في المتصفح عن خطأ غير مُلتقَط. وبالنسبة للمختبِر فإن throw نتيجة متوقعة يجب فحصها: الرسالة، وما يصل إلى المستخدم أو إلى عميل الواجهة البرمجية (API).

جرّبها: منسّق JavaScript جرّبها: مولّد جداول القرار

الحلقات والمعاملات والقيم المُعادة

الدالة (function) منطقٌ له اسم ومدخلات ومخرج. معاملاتها (parameters) هي الأسماء بين القوسين، ووسائط الاستدعاء (arguments) هي القيم التي تُمرَّر إليها، والقيمة المُعادة (return value) هي ما يرجع منها. وهذا يطابق الاختبار مباشرةً: الوسائط هي مدخلات اختبارك، والقيمة المُعادة هي النتيجة الفعلية التي تقارنها بالنتيجة المتوقعة. وتعرض دروس التغطية أيضاً شيفرة TypeScript التي تضيف الأنواع بعد الأسماء: total: number تُقرأ «الإجمالي رقم»، وitems: Item[] تُقرأ «items قائمة من قيم Item» (وItem نوع عرّفه الفريق في موضع آخر)، و): number بعد القوسين تُقرأ «تعيد رقماً». ويفحص TypeScript هذه الأنواع قبل تشغيل الشيفرة ثم يحذفها من شيفرة JavaScript التي تعمل فعلاً، فلا تفحص القيم التي يتلقاها الاستدعاء وقت التشغيل، كالقيم الآتية من استجابة واجهة برمجية.

الحلقة (loop) تكرّر كتلة. لحلقة for بداية، وشرط يُفحص قبل كل دورة، وخطوة بعد كل دورة؛ وحلقة while تتكرر ما دام شرطها متحققاً. وكلتاهما قد لا تُنفَّذ ولا مرة.

  • function deliveryFee(total, express) تُقرأ «دالة اسمها deliveryFee لها مدخلان». والاستدعاء deliveryFee(200, false) يجعل total يساوي ⁦200⁩ وexpress يساوي false؛ والوسيط المفقود قيمته undefined. والاستدعاء داخل الشيفرة، مثل Math.floor(total / 10)، يشغّل دالة أخرى ويستخدم القيمة التي تعيدها؛ وابحث عن الدوال المدمجة في MDN (تقرّب Math.floor إلى الأسفل: Math.floor(12.5) تساوي ⁦12⁩).
  • for (let i = 0; i < items.length; i++) { … } تُقرأ «ابدأ بـi يساوي ⁦0⁩؛ وما دام i أقل من عدد العناصر نفّذ الكتلة ثم أضف ⁦1⁩ إلى i». تبدأ المواقع في القائمة من ⁦0⁩: فـitems[0] هو العنصر الأول، وitems[i] العنصر في الموقع i، وitems[items.length - 1] آخر عنصر. والبدء من ⁦1⁩ يتخطى العنصر الأول، و<= تنفّذ دورة زائدة.
  • for (const item of items) { … } تُقرأ «لكل عنصر في items، بالترتيب، نفّذ الكتلة». ليس فيها عدّاد قد يُضبط خطأً، لكن القائمة الفارغة تعني صفر دورات هنا أيضاً.
  • while (attempts < 3) { … } تُقرأ «كرّر ما دامت المحاولات أقل من ⁦3⁩». وإن لم يغيّر شيء في الكتلة قيمة attempts فلن تنتهي الحلقة أبداً، وتتجمّد الصفحة أو يعلق الاختبار.
  • تتبّع كل حلقة بصفر دورات ودورة واحدة وعدة دورات: سلة فارغة، وعنصر واحد، وعناصر كثيرة.

مثال تطبيقي: تتبّع دالة رسوم يدوياً

المتطلب: «التوصيل بـ⁦15.00⁩ ريالاً. والطلبات بقيمة ⁦200.00⁩ ريال فأكثر توصيلها مجاني. والتوصيل السريع يضيف ⁦10.00⁩ ريالات، حتى إلى الطلبات ذات التوصيل المجاني. ويُرفض الإجمالي الذي يساوي صفراً أو أقل». وتأتي دالة المطور بعد خطوات التتبّع أدناه، بأرقام الأسطر كما في دروس التغطية؛ فارجع إلى كل سطر فيها وأنت تقرأ الخطوات.

أنشئ جدول تتبّع (trace table) فيه صف لكل مُدخل، وأعمدة للأسطر المنفَّذة ونتيجة كل قرار والقيمة المُعادة. امشِ في الشيفرة سطراً سطراً واكتب القيمة الجديدة لكل متغيّر، ولا تقارن القيمة المُعادة بالنتيجة المتوقعة المأخوذة من المتطلب إلا بعد ذلك. واختر مدخلات على جانبي كل مقارنة:

  • deliveryFee(0, false): في السطر ⁦2⁩ نتيجة 0 <= 0 هي true، فيرمي السطر ⁦3⁩ الخطأ (throw) ولا تُنفَّذ الأسطر من ⁦5⁩ إلى ⁦12⁩ أبداً. والمتطلب يتوقع الرفض: مطابق.
  • deliveryFee(50, false): القرارات الثلاثة كلها false، فتبقى الرسوم ⁦15⁩ ويعيد السطر ⁦12⁩ القيمة ⁦15⁩. مطابق.
  • deliveryFee(250, true): نتيجة السطر ⁦6⁩ هي true فتصبح الرسوم ⁦0⁩، ونتيجة السطر ⁦9⁩ هي true فتصبح ⁦10⁩. تعيد الدالة ⁦10⁩ كما يطلب المتطلب.
  • deliveryFee(200, false): نتيجة 200 > 200 هي false، فيُتجاوز السطر ⁦7⁩ وتعيد الدالة ⁦15⁩ بينما يتوقع المتطلب ⁦0⁩. يسلك هذا المُدخل مسار ⁦50⁩ نفسه، والقيمة الحدّية وحدها تكشف العيب. شغّل الاختبار لتأكيد الإخفاق، ثم أبلغ عنه بالمُدخل والنتيجتين المتوقعة والفعلية والسطر ⁦6⁩.
 1  function deliveryFee(total, express) {
 2    if (total <= 0) {
 3      throw new Error('Order total must be positive');
 4    }
 5    let fee = 15;
 6    if (total > 200) {
 7      fee = 0;
 8    }
 9    if (express) {
10      fee = fee + 10;
11    }
12    return fee;
13  }
جدول تتبّع الدالة deliveryFee لأربعة مدخلات: المُدخل ⁦200⁩ يسلك مسار ⁦50⁩ نفسه لأن نتيجة 200 > 200 هي false، فيعيد ⁦15⁩ بينما يتوقع المتطلب توصيلاً مجانياً.
وسائط الاستدعاء: total وexpressالسطر ⁦2⁩total <= 0السطر ⁦6⁩total > 200السطر ⁦9⁩expressالأسطر المنفَّذةالقيمة المُعادة
0, falsetrueلم يصل إليه التنفيذلم يصل إليه التنفيذ⁦2, 3⁩يرمي Errorالمتطلب: الرفضنجاح
50, falsefalsefalsefalse⁦2, 5, 6, 9, 12⁩15المتطلب: ⁦15⁩نجاح
250, truefalsetruetrue⁦2, 5, 6, 7, 9, 10, 12⁩10المتطلب: ⁦10⁩نجاح
200, falsefalsefalsefalse⁦2, 5, 6, 9, 12⁩15المتطلب: ⁦0⁩فشل
  • الشرط true: تُنفَّذ الكتلة التي تحته
  • القيمة الحدّية: مسار ⁦50⁩ نفسه ونتيجة خاطئة

الشرطة تعني أن التنفيذ لم يصل إلى السطر: فقد توقف الاستدعاء الأول عند throw في السطر ⁦3⁩.

جرّبها: مولّد القيم الحدّية

أخطاء شائعة

  • قراءة = المفردة على أنها مقارنة: fee = 0 تغيّر الرسوم، أما المقارنة فتُكتب بـ=== أو !== أو == أو < أو <= أو > أو >=.
  • أخذ النتيجة المتوقعة من الشيفرة التي تتبّعتها للتو. فالتتبّع يخبرك بما تفعله الشيفرة، أما ما يجب أن تفعله فيأتي من المتطلب أو من مالك المنتج.
  • افتراض أن كل سطر يُنفَّذ: بعد return أو throw يُتجاوز باقي الدالة، ولا تُنفَّذ إلا كتلة واحدة من سلسلة if / else if / else.
  • تتبّع مُدخل واحد من المسار السعيد (happy path) والتوقف عنده. خذ كل قرار في الاتجاهين، وضع قيمة على جانبي كل مقارنة، وشغّل كل حلقة صفراً ومرة ومرات.
  • إهمال الأقواس والتقييم المختصر (short-circuit) في الشروط: a || b && c ليست (a || b) && c، والطرف الثاني من && لا يُقيَّم أبداً إذا كانت نتيجة الأول false.
  • إبقاء التتبّع في ذهنك. اكتب الجدول؛ فالحلقات والمتغيّرات التي يُعاد إسنادها هي حيث يخطئ التتبّع الذهني.

من منظور ضمان الجودة

في الفريق تقرأ الشيفرة عندما يصل تغيير. ففي طلب الدمج (Pull Request) ابحث عن الشروط والحدود ومسارات الخطأ التي يضيفها أو يغيّرها، وحوّل كلاً منها إلى فكرة اختبار أو سؤال («السطر ⁦6⁩ يقول > 200 والقصة تقول ⁦200⁩ فأكثر، فأيهما الصحيح؟»). وقراءة الشيفرة دون تشغيلها اختبارٌ ساكن (static testing)، والتتبّع اليدوي صورة سريعة منه تُسمّى أحياناً التشغيل الجاف (dry run) أو الفحص المكتبي (desk check)، وأفضل ما يكون حين تجلس إلى جانب المطور.

سجّل ما تجده كما تسجّل أي اختبار آخر: المُدخل، والأسطر المنفَّذة، والنتيجة المتوقعة من المتطلب، والنتيجة الفعلية. والتتبّع يدلّك على عيب مُشتبه به، فشغّل الاختبار متى استطعت لتلاحظ الإخفاق الذي يسبّبه. وذِكر المُدخل والسطر المشتبه به في تقرير الخطأ يوفّر وقت المطور، لكن التقرير يبقى وصفاً للإخفاق المُلاحَظ، لا مجرد «الشيفرة خاطئة». ولست مطالباً باقتراح الإصلاح، وإن اقترحته فاكتبه على أنه اقتراح.

تمرين عملي

تتبّع دالة إجمالي السلة

المطلوب

المتطلب: «إجمالي السلة هو مجموع السعر × الكمية لكل عنصر. والقسيمة SAVE10 تخصم ⁦10.00⁩ ريالات من الإجماليات البالغة ⁦50.00⁩ ريالاً فأكثر». تتبّع الدالة أدناه يدوياً للاستدعاءات الثلاثة المكتوبة تحتها.

سجّل لكل استدعاء الأسطر المنفَّذة، ونتيجة كل قرار، وقيمة total بعد كل خطوة، والقيمة المُعادة. ثم قارن بالنتيجة المتوقعة من المتطلب، وصِف أي عيب تجده.

المادة
 1  function cartTotal(items, coupon) {
 2    let total = 0;
 3    for (let i = 1; i < items.length; i++) {
 4      total = total + items[i].price * items[i].qty;
 5    }
 6    if (coupon === 'SAVE10' && total >= 50) {
 7      total = total - 10;
 8    }
 9    return total;
10  }

A  cartTotal([{ price: 30, qty: 2 }], 'SAVE10')
B  cartTotal([{ price: 20, qty: 1 }, { price: 15, qty: 2 }], '')
C  cartTotal([], 'SAVE10')
الخطوات
  1. ارسم جدول التتبّع: المُدخل، والأسطر المنفَّذة، والقرارات، وقيمة total بعد كل خطوة، والقيمة المُعادة.
  2. تتبّع الاستدعاءات A وB وC سطراً سطراً، مع عدّ دورات الحلقة.
  3. استخرج النتيجة المتوقعة لكل استدعاء من المتطلب وحده.
  4. قارن، وحدّد السطر الذي تشك فيه، واكتب ملخص العيب في جملة واحدة.
إظهار الإجابة النموذجية
الإجابة النموذجية

A: يضبط السطر ⁦2⁩ قيمة total على ⁦0⁩. ويبدأ السطر ⁦3⁩ بـi يساوي ⁦1⁩، ونتيجة 1 < 1 هي false، فلا يُنفَّذ جسم الحلقة أبداً. السطر ⁦6⁩: القسيمة مطابقة لكن نتيجة 0 >= 50 هي false، فيُتجاوز السطر ⁦7⁩. تعيد الدالة ⁦0⁩. المتوقع: ⁦60 - 10 = 50⁩. يفشل الاختبار.

B: تبدأ total من ⁦0⁩. الدورة الأولى: i يساوي ⁦1⁩ ونتيجة 1 < 2 هي true، فتصبح total ⁦0 + 15 × 2 = 30⁩. الدورة الثانية: i يساوي ⁦2⁩ ونتيجة 2 < 2 هي false، فتنتهي الحلقة. السطر ⁦6⁩: نتيجة '' === 'SAVE10' هي false، فيتوقف && عندها. تعيد الدالة ⁦30⁩. المتوقع: ⁦20 + 30 = 50⁩. يفشل الاختبار.

C: لا تُنفَّذ الحلقة ولا مرة، وفحص القسيمة نتيجته false. تعيد الدالة ⁦0⁩ كما هو متوقع. ينجح هذا الاستدعاء رغم أن الشيفرة خاطئة: فالسلة الفارغة تخفي العيب.

العيب: يبدأ السطر ⁦3⁩ الحلقة من i = 1، فلا يُضاف العنصر الأول أبداً، والصحيح البدء من i = 0. الملخص: «إجمالي السلة يُسقط العنصر الأول: عنصر واحد بسعر ⁦30.00⁩ × ⁦2⁩ مع SAVE10 يعطي ⁦0⁩ بدلاً من ⁦50.00⁩». وبعد الإصلاح أعد تشغيل A وB وC لتأكيده (اختبار التأكيد). والآن يصل الاستدعاء A إلى السطر ⁦7⁩ لأول مرة، فاختبر القسيمة أيضاً عند حدّها بإجماليين ⁦49.99⁩ و⁦50.00⁩.

أسئلة شائعة

هل أحتاج إلى تعلّم البرمجة لأقرأ الشيفرة بهذه الطريقة؟

لا. لتتبّع المنطق يكفي أن تميّز القيم والمقارنات والقرارات والحلقات وreturn وthrow، وهذا ما يغطيه الدرس. أما كتابة شيفرتك الخاصة فتأتي لاحقاً في دروس أتمتة الاختبار. ابدأ بالدوال الصغيرة وبطلبات الدمج التي يناقشها فريقك أصلاً.

ماذا لو كان فريقي لا يستخدم JavaScript؟

اللبنات الأساسية واحدة في اللغات الأخرى. تستخدم Java وC# العوامل نفسها && و|| و! والأقواس المعقوفة وحلقات for. أما Python فتكتب and وor وnot، وتحدّد الكتل بالإزاحة بدلاً من الأقواس، وحلقة for فيها تمرّ على عناصر القائمة مباشرةً. وجدول التتبّع يصلح لها جميعاً.

ما الفرق بين == و===؟

=== (المساواة الصارمة) نتيجتها true فقط عندما يتساوى النوع والقيمة معاً. أما == (المساواة المتساهلة) فتحوّل الأنواع أولاً، فتكون نتيجة كلٍّ من '5' == 5 و0 == '' هي true. ولهذا تشترط فرق كثيرة استخدام ===؛ وإذا رأيت == في مقارنة مع مدخلات المستخدم فاختبر برقم مكتوب نصاً وبقيمة فارغة.

أين يجد المختبِر شيفرة ليقرأها؟

في طلب الدمج (Pull Request أو Merge Request) الخاص بالقصة التي تختبرها، وفي اختبارات الوحدة المجاورة للشيفرة، وفي تقرير التغطية الذي يعرض الشيفرة سطراً سطراً، وفي صفحات الويب عبر أدوات المطور في المتصفح، حيث تعرض لوحة Sources أو Debugger السكربتات التي حمّلتها الصفحة. اطلب صلاحية القراءة في المستودع؛ فكثير من الفرق تمنحها للمختبِرين.

المراجع

  • ECMAScript® Language Specification (ECMA-262)Ecma International / TC39معيار لغة JavaScript، بما فيه قواعد RegExp ودلالاتها، وJSON.parse/JSON.stringify، وكائن Date.
  • JavaScript — MDNMDN Web Docs (Mozilla)دليل MDN ومرجعه للغة JavaScript: صياغة اللغة وأنواعها وكائناتها ومكوّناتها المدمجة كما تنفّذها المتصفحات.
  • ISTQB Certified Tester Foundation Level (CTFL) v4.0ISTQB · 2023المنهج التأسيسي لاختبار البرمجيات: مستويات الاختبار وأنواعه وتقنيات تصميم الاختبارات وإدارة الاختبار والأدوات.
  • ISTQB GlossaryISTQBالتعريفات القياسية لمصطلحات الاختبار — حالة الاختبار واختبار الانحدار والخطورة والأولوية وتحليل القيم الحدّية وغيرها.

تدرّب بأدوات متقن

تجميل كود JavaScript وTypeScript بمسافات بادئة وتباعد متسقين.

التنسيق

ولّد القيم الحدّية (min-1 وmin وmin+1 والقيمة الاسمية وmax-1 وmax وmax+1) للقيود الرقمية وقيود الطول.

تصميم الاختبارات

أنشئ جداول القرار من الشروط والإجراءات، وولّد جميع تركيبات القواعد، واختزل المستحيل منها.

تصميم الاختبارات

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة