۱۳۸۷/۱۰/۰۸

آشنايي با آزمايش واحد (unit testing) در دات نت، قسمت 2


دلايل شانه خالي كردن از آزمايش واحد!

1- نوشتن آزمايشات زمان زيادي را به خود اختصاص خواهند داد.

مهمترين دليلي كه برنامه‌نويس‌ها به سبب آن از نوشتن آزمايشات واحد امتناع مي‌كنند، همين موضوع است. اكثر افراد به آزمايش به‌عنوان مرحله آخر توسعه فكر مي‌كنند. اگر اين چنين است، بله! نوشتن آزمايش‌هاي واحد واقعا سخت و زمانگير خواهند بود. به همين جهت براي جلوگيري از اين مساله روش pay-as-you-go مطرح شده است (ماخذ: كتاب Pragmatic Unit Testing در سي شارپ). يعني با اضافه شدن هر واحد كوچكي به سيستم، آزمايش واحد آن‌را نيز تهيه كنيد. به اين صورت در طول توسعه سيستم با باگ‌هاي كمتري نيز برخورد خواهيد داشت چون اجزاي آن‌را در اين حين به تفصيل مورد بررسي قرار داده‌ايد. اثر اين روش را در شكل زير مي‌توانيد ملاحظه نمائيد (تصويري از همان كتاب ذكر شده)




نوشتن آزمايشات واحد زمانبر هستند اما توسعه پيوسته آن‌ها با به تاخير انداختن آزمايشات به انتهاي پروژه، همانند تصوير فوق تاثير بسيار قابل توجهي در بهره وري شما خواهند داشت.

بنابراين اگر عنوان مي‌كنيد كه وقت نداريد آزمايش واحد بنويسيد، به چند سؤال زير پاسخ دهيد:
الف) چه مقدار زمان را صرف ديباگ كردن كدهاي خود يا ديگران مي‌كنيد؟
ب) چه ميزان زمان را صرف بازنويسي كدي كرده‌ايد كه تصور مي‌رفت درست كار مي‌كند اما اكنون بسيار مشكل زا ظاهر شده است؟
ج) چه مقدار زمان را صرف اين كرده‌ايد كه منشاء باگ گزارش شده در برنامه را كشف كنيد؟

براي افرادي كه آزمايشات واحد را در حين پروسه توسعه در نظر نمي‌گيرند، اين مقادير بالا است و با ازدياد تعداد خطوط سورس كدها، اين ارقام سير صعودي خواهند داشت.



تصويري از كتاب xUnit Test Patterns ، كه بيانگر كاهش زمان و هزينه كد نويسي در طول زمان با رعايت اصول آزمايشات واحد است

2- اجراي آزمايشات واحد زمان زيادي را تلف مي‌كند.

نبايد اينطور باشد. عموما اجراي هزاران آزمايش واحد، بايد در كسري از ثانيه صورت گيرد. (براي اطلاعات بيشتر به قسمت حد و مرز يك آزمايش واحد در قسمت قبل مراجعه نمائيد)

3- امكان تهيه آزمايشات واحد براي كدهاي قديمي ( legacy code ) من وجود ندارد

براي بسياري از برنامه نويس‌ها، تهيه آزمايش واحد براي كدهاي قديمي بسيار مشكل است زيرا شكستن آن‌ها به واحدهاي كوچكتر قابل آزمايش بسيار خطرناك و پرهزينه است و ممكن است سبب از كار افتادن سيستم آن‌ها گردد. اينجا مشكل از آزمايش واحد نيست. مشكل از ضعف برنامه نويسي آن سيستم است. روش refactoring ، طراحي مجدد و نوشتن آزمايشات واحد، به تدريج سبب طراحي بهتر برنامه از ديدگاه‌هاي شيءگرايي شده و نگهداري سيستم را در طولاني مدت ساده‌تر مي‌سازد. آزمايشات واحد اين نوع سيستم‌ها را از حالت فلج بودن خارج مي‌سازد.

4- كار من نيست كه كدهاي نوشته شده را آزمايش كنم!

بايد درنظر داشته باشيد كه اين هم كار شما نيست كه انبوهي از كدهاي مشكل دار را به واحد بررسي كننده آن تحويل دهيد! همچنين اگر تيم آزمايشات و كنترل كيفيت به اين نتيجه برسد كه عموما از كدهاي شما كمتر مي‌توان باگ گرفت، اين امر سبب معروفيت و تضمين شغلي شما خواهد شد.
همچنين اين كار شما است كه تضمين كنيد واحد تهيه شده مقصود مورد نظر را ارائه مي‌دهد و اين‌كار را با ارائه يك يا چندين آزمايش واحد مي‌توان اثبات كرد.

5- تنها قسمتي از سيستم به من واگذار شده است و من دقيقا نمي‌دانم كه رفتار كلي آن چيست. بنابراين آن را نمي‌توانم آزمايش كنم!

اگر واقعا نمي‌دانيد كه اين كد قرار است چه كاري را انجام دهيد به طور قطع الان زمان مناسبي براي كد نويسي آن نيست!

6- كد من كامپايل مي‌شود!

بايد دقت داشت كه كامپايلر فقط syntax كدهاي شما را بررسي كرده و خطاهاي آن‌را گوشزد مي‌كند و نه نحوه‌ي عملكرد آن‌را.

7- من براي نوشتن آزمايشات حقوق نمي‌گيرم!

بايد اذعان داشت كه به شما جهت صرف تمام وقت يك روز خود براي ديباگ كردن يك خطا هم حقوق نمي‌دهند! شما براي تهيه يك كد قابل قبول و قابل اجرا حقوق مي‌گيريد و آزمايش واحد نيز ابزاري است جهت نيل به اين مقصود (همانند يك IDE و يا يك كامپايلر).

8- احساس گناه خواهم كرد اگر تيم فني كنترل كيفيت و آزمايشات را از كار بي كار كنم!!

نگران نباشيد، اين اتفاق نخواهد افتاد! بحث ما در اينجا آزمايش كوچكترين اجزا و واحدهاي يك سيستم است. موارد ديگري مانند functional testing, acceptance testing, performance & environmental testing, validation & verification, formal analysis توسط تيم‌هاي كنترل كيفيت و آزمايشات هنوز بايد بررسي شوند.

9- شركت من اجازه اجراي آزمايشات واحد را بر روي سيستم‌هاي در حال اجرا نمي‌دهد.

قرار هم نيست بدهد! چون ديگر نام آن آزمايش واحد نخواهد بود. اين آزمايشات بايد بر روي سيستم شما و توسط ابزار و امكانات شما صورت گيرد.


پ.ن.
در هشتمين دليل ذكر شده، از acceptance testing نامبرده شده. تفاوت آن با unit testing به صورت زير است:

آزمايش واحد:
توسط برنامه نويس‌ها تعريف مي‌شود
سبب اطمينان خاطر برنامه نويس‌ها خواهد شد
واحدهاي كوچك سيستم را مورد بررسي قرار مي‌دهد
يك آزمايش سطح پائين ( low level ) به شمار مي‌رود
بسيار سريع اجرا مي‌شود
به صورت خودكار (100 درصد خودكار است) و با برنامه نويسي قابل كنترل است

اما در مقابل آزمايش پذيرش به صورت زير است:
توسط مصرف كنندگان تعريف مي‌شود
سبب اطمينان خاطر مصرف كنندگان مي‌شود.
كل برنامه مورد آزمايش قرار مي‌گيرد
يك آزمايش سطح بالا ( high level ) به شمار مي‌رود
ممكن است طولاني باشد
عموما به صورت دستي يا توسط يك سري اسكريپت اجرا مي‌شود
مثال : گزارش ماهيانه بايد جمع صحيحي از تمام صفحات را در آخرين برگه گزارش به همراه داشته باشد


ادامه دارد...