أهمية الاختبارات في مجال تطوير البرمجيات وأنواعها

0
يبقى الهاجس الأكبر عند المبرمج بعد هاجس إنجاز المطلوب هو التيقن من أن ما تم إنجازه يعمل بالشكل المنتظر وتحت جميع الظروف الممكنة، فالتطبيق الذي يقوم بعملية جمع عددين مثلا، بمقدور المبرمج إنجازه بسهولة، لكن هذا لا يكفي إذ ينبغي اختبار قدرة التطبيق على القيام بعملية الجمع بشكل صحيح، وقد يتحقق ذلك من خلال اختباره بأي عددين، لكن ماذا لو كان العددان المدخلان أو أحدهما أكبر من الحجم الممكن لنوع البيانات المستعمل؟ وماذا لو كان أحد العددين المدخلين نصا؟ وغيرها من الأسئلة التي تؤرق المبرمج حتى بعد انتهائه من إنجاز العمل المطلوب، ويبقى واضعا يده على قلبه ينتظر في كل لحظة اتصالا من العميل يقول له: هنالك خطأ في البرنامج، وهذا شر دون شر، أما الشر المستطير أن ينتج عن الخطأ مصائب وطوام فيتصل بك العميل أو تتصل بك الشرطة :) طبعا بعد أن قدم العميل شكوى ضدك.

فليحفظك الله وليجنبك كل سوء، وحديثي هنا ليس لتخويفك من عملية الاختبار ولكن لإبراز أهميتها البالغة في صناعة البرمجيات، إذ أن أي برنامج لم يتم اختباره بشكل فعلي فلا يمكن الوثوق فيه، ولا أعني بحديثي عن الاختبارات تنفيذ التطبيق والتحقق من نتائجه يدويا، لا أقصد هذا، وإنما حديثي عن نوع آخر من الاختبارات.
وقد تنظر إلي في جزع وترى أنني أبالغ في تهويل أهمية الاختبارات وقد تقول بسخرية: ولما لا أقوم بالاختبارات اليدوية غصبا عنك فأربح الوقت وأوفر الجهد، وهنا لن أجيب بل سأعود بك إلى المثال الذي قدمناه في الأول عن عملية الجمع، ولنفترض أنك كتبت الكود التالي الذي يقوم بعملية الجمع (وتذكر أن هذا مجرد مثال بسيط وصغير وأن ساحات البرمجة حبلى بالكثير من مواضع ورود الخطأ):
        int Add(int a, int b)
        {
            return a * b;
        }

لا شك أنه كود بسيط يجمع متغيرين رقميين من نوع int، غير أنه لو دققت في هذا الكود ستجد أنني بدل أن أضع رابط الجمع + وضعت رابط الضرب *، وهذا الخطأ وارد جدا في البرمجة وأمثاله كثر.
لنفترض أنك لم تنتبه إلى الأمر، ثم جربت الاختبار اليدوي، ومررت للمتغير الأول القيمة 2، وللمتغير الثاني نفس القيمة أي 2، كيف ستكون نتيجة العملية؟ طبعا 2 في 2 النتيجة هي 4، وستبتسم بشدة وتنتقل إلى جزء آخر من برنامجك لأنك اختبرت عملية الجمع يدويا وحصلت على نتيجة صحيحة، لكن لن تصطدم بالأمر الواقع حتى يقع البرنامج بين يدي العميل ويجرب قيما رقمية أخرى، فيؤثر ذلك سلبا على شغل العميل وعلى سمعتك، فاحذر أن تثق بالاختبارات اليدوية وحدها لأنها لا تعكس الصورة الحقيقية لاشتغال الكود.
أضف إلى ذلك أن الاختبارات اليدوية مكلفة للوقت والجهد (والمال طبعا) لأنك ستضطر إلى اختبار النظام بشكل عام عند إضافة أي جزئية جديدة أو تعديل جزئية سابقة. تريد مثالا:
لنفترض أنك تشتغل على نظام تجاري وأضفت في الجزء الخاص بإصدار الفواتير طريقة دفع جديدة، إذا أردت أن تختبر هذه الجزئية فقط فعليك تشغيل البرنامج ثم إضافة فاتورة جديدة، وإضافة بعض المنتوجات إليها، ووضع وصف الفاتورة وتاريخهاـ وتحديد العميل، ثم تختار عملية الدفع الجديدة وتضغط على زر الحفظ لتتحقق من أنها تشتغل ثم تذهب لقاعدة البيانات لتتأكد من ذلك، سيناريو سيء جدا، خاصة إذا تكرر بشكل كبير..
الآن بعد أن اقتنعت شيئا ما بحديثي، قد تسألني: وما هو الحل يا ترى؟
الحل هو أن تكتب الاختبارات الأحادية Unit Tests لتختبر أكوادك بشكل تلقائي، حتى تضمن أنها تؤدي المطلوب بالشكل المتوقع، وحتى تتحقق عند تعديل الكود في جزئية معينة أن الوحدة الخاصة به ما تزال تشتغل بنجاح من خلال تشغيل الاختبار الأحادي الخاص بها، وغيرها من المزايا القوية التي ستمنحك الثقة في عملك، وسترفع من جودة الكود الذي تكتبته، والأهم من كل ذلك أنها ستخبرك هل كودك يؤدي المطلوب منه كما ينبغي.
وقد تسألني: متى ينبغي أن أختبر الكود الذي أكتبه؟
وسأجيبك بشكل عام:  أي كود يمكن اختباره يجب اختباره
ماهي الاختبارات؟
هي أكواد أخرى نقوم بكتابتها لاختبار الأكواد الأولى التي نريدها أن تقوم بالمطلوب.
ماهي أنواع الاختبارات؟
توجد عدة أنواع من الاختبارات أشهرها الاختبارات الأحادية Unit Tests، واختبارات التكامل Integration Tests، واختبارات القبول Acceptance Testing (ATPs)، ويوجد غيرها..
ماهي الاختبارات الأحادية Unit Tesing؟
الاختبارات الأحادية هي اختبارات نقوم بكتابتها من أجل التحقق من أن الوحدات البرمجية التي نقوم بكتابتها تؤدي المطلوب منها كما ينبغي، والمقصود بالوحدات Units، هي كل جزء من الكود (في الغالب نقصد بها الوظائف Methods) لا يقوم باستدعاء وظائف أخرى، والذي يقوم بعمل واحد فقط (لأنه من غير الجيد برمجيا أن تقوم الوظيفة بأكثر من عمل والواجب في هذه الحالة تقسيمها إلى وظائف فرعية) وأن تكون هذه الوحدة لا تحتوي على عدة مسارات تنفيذ، كأن يكون بداخلها if else statement مثلا، لأنه ينبغي اختبار نفس الوحدة في مختلف مسارات تنفيذها لنضمن بأنه تم اختبارها بشكل كامل وهنا نتحدث عن نسبة التغطية Code Coverage والذي نقصد به نسبة الكود الذي تم اختياره.
كما ينبغي أن تكون الوحدة (الوظيفة) المراد اختبارها مستقلة بذاتها Dependant وغير مرتبطة بمكونات خارجية، لأن كثرة الارتباطات تصعب عملية الاختبار إذ ينبغي توفير هذه الارتباطات عند الاختبار من أجل تنفيذه، غير أن هذا الأمر ممكن فلا تشغل بالك، لكن حاول دائما وأنت تكتب الكود أن تضع في بالك محاولة فكه وعزله عن الارتباطات من خلال استعمال بعض الأساليب والآليات مثل Dependency Injection وإن أحببت التعمق أكثر في هذا الباب فعد إلى كتابنا: المختصر المفيد في مبادئ SOLID والذي شرحنا فيه المبادئ الخمسة بكتابة كود قابل للاختبار Testable، قابل للصيانة Maintainable، قابل للزيادة Extensible.
إذن فالاختبارات الأحادية هي اختبارات نقوم بكتابتها لاختبار وحدات برمجية معزولة وتقوم بدور واحد، من أجل التحقق من أنها بالفعل تقوم بهذا الدور .
النوع الثاني من الاختبارات هو اختبارات التكامل Integration Tests، وهو يسمح لنا بالتحقق من أن مجموعة من الوحدات التي تشتغل مع بعضها البعض تؤدي النتيجة المطلوبة كما ينبغي، وتسمح لنا اختبارات التكامل بالتحقق من الارتباطات Dependencies أيضا، وتوجد عدة طرق لذلك سنراها في وقتها إن شاء الله،
النوع الثالث من الاختبارات هو اختبارات القبول Acceptance Testing، والذي يكون عادة عند الانتهاء من المشروع حيث تجتمع كافة أطراف المشروع لمناقشة النتيجة المحصل عليها وهل هي موافقة لما تم اعتماده عند تحليل المشروع.

لا يوجد تعليقات

أضف تعليق