توسعه آزمون محور
در این مقاله روش توسعهی آزمون محور (Test Driven Development) معرفی و بررسی شده است. توسعهی آزمون محور چیست؟
بر اساس تعریف اسکات امبلر (Scott W. Ambler) توسعهی آزمون محور یک روش جدید برای توسعه است که در آن ایدهی ساختن تستها پیش از توسعهی کد اصلی با روش بازتولید (Refactoring) تلفیق میشود. مفاهیم این مدل توسعه برای بار اول توسط بک (Beck 2003) بررسی شده است. استفاده از آزمونها برای حصول اطمینان از کیفیت و کارائی محصولات نرمافزاری ایدهی جدیدی نیست، نکتهی جدید در این روش اهمیت ویژهی این آزمونها و به خصوص تاکید بسیار زیاد بر این نکتهی کلیدی است که توسعه با نوشتن تستها آغاز میشود. این نگاه طراحی تستها را از یکی از ابزارهای توسعه تبدیل به یک روش و متدولوژی توسعه میکند که تمامی بخشهای توسعه، نظیر تحلیل، طراحی، و پیادهسازی را هم تحت تاثیر قرار میدهد. این تاثیر به شکل فشرده عبارتست از:
تحلیل به معنای تحلیل نیازمندیهای مشتری و تبدیل آن به صورت یکدسته از آزمونهای پذیرش است. قراردا ما با مشتری تولید نرمافزاری خواهد بود که آزمونهای مورد توافق را با موفقیت پشت سر قرار دهد. محدودهی پروژه با مجموعهی این تستها تعریف میشود. خروجی تحلیل برنامهی تست است و...
منظور از طراحی، رسیدن به توافقی در طرح کلی سیستم است که تیم پروژه معتقد است میتواند آزمونها را بگذراند. طراحی به هنگام نوشتن آزمونها انجام میشود. کدهای آزمون به خوبی میتوانند اجزای مورد انتظار سیستم و روش کار آنها را نشان دهند.
وظیفهی برنامهنویس نوشتن کدی است که آزمون را بگذراند. این نکته کلیدی ترین نکتهی مثبت این روش است که کمک میکند تا وظایف برنامهنویس به شکل دقیق و روشنی توصیف شود. اگر یکی از دلایل عمدهی شکست و یا تعویق تلاشهای توسعه در ضعف کنترل برنامهنویسان باشد، توسعهی آزمون محور کمکی کلیدی برای رفع این معضل خواهد بود. توسعهی آزمون محور چگونه کار میکند؟
کانینگهام (لینک) و امبلر روش به کار بستن توسعهی آزمون محور را توضح دادهاند. مطابق با این توصیهها، فرآیند توسعه بر اساس این روش به شکل زیر است:
به آنچه قرار است انجام شود فکر کنید.
فکر کنید چگونه میتوان آنرا تست کرد.
آزمون کوچکی بنویسید، به چگونگی پیادهسازی ارتباطات فکر کنید.
آنقدر کد تولید کند که آزمون با خطا اجرا شود. (فقط کامپایل شود.)
آزمون را اجرا کنید و شکست خوردن آنرا ببینید. حال مطمئن هستید آزمون شما اجرا میشود.
فقط آنقدر کد بنویسید که آزمون با موفقیت اجرا شود. و همچنین باعث اشکال در تستهای قبلی نشود.
اگر بخشهای از کد تکراری و یا نامناسب است آن بخشهای را بازنویسی کنید (Refactor) مراقب باشید تستها هنوز با موفقیت انجام شوند.
مراحل بالا را آنقدر تکرار کنید که آزمون جدیدی قابل تعریف نباشد. نکتهی کلیدی در بکار بستین این روش آن است که در هر دور حداقل کد لازم برای گذر است تستها نوشته شود. اگر برنامهنویس فکر میکد کاری که بایستی انجام دهد سادهتر از آنست که نیاز سیستم جواب داده شود، این بدان معنا است که تستها درست نوشته نشدهآند و بایستی تصحیح شوند نه آنکه برنامهنویس بایستی کد پیچیدهتری تولید کند. مککی این روش را به خوبی در این مثال توضیح داده است که در آن به شکل اغراق آمیزی کد صرفا با جواب دادن به تست توسعه داده میشود. انواع آزمون و آزمونهای خودکار (Automated) امبلر آزمونها را به دو دستهی آزمونهای پذیرش و تستهای توسعه تقسیم میکند. آزمونهای پذیرش، بیشتر بر اساس نیازمندیهای مشتری و بر اساس تحلیل نیازمندیهای شکل میگیرند، در صورتیکه آزمونهای توسعه بیشتر بر اساس نیازمندیهای عملیاتی و بر اساس طراحی تنظیم میشوند. فارغ از این تقسیم بندی به نظر میرسد منظور از آزمون، تکه برنامهای است که نوشته و اجرا میشود. آزمونهای پذیرش ممکن است به صورت دستی و توسط یک شخص انجام شوند هر چقدر به آزمونهای توسعه نزدیکتر میشویم نیاز به اجرای خودکار این تستها بیشتر میشود.
اصولا توسعهی آزمون محور بر اساس توسعهی تستهای خودکار و سیستمی که بتواند آنها را با سرعت زیاد انجام دهد پایهریزی میشود. اگر نتوانیم این سیستم خودکار تستها را بسازیم عملا این روش تمامی کارآمدی خود را از دست خواهد داد.
از اینرو انتخاب و موفقیت این روش تا حد زیادی بستگی به انتخاب و کارآمدی سیستم آزمون خودکار دارد. ابزارهای آزمون در ویژوال استودیو(Visual Studio)
به نظر میرسد ابزارهای ویژوال استودیو به خصوص امکانات آن در محیط توسعهی ویژوال استودیوی ۲۰۱۰ و همچنین امکانات مایکروسافت تست منیجر(Microsoft Test Manager 2010) به خوبی پاسخگوی بسیاری از نیازمندیهای توسعهی آزمون محور برای پروژههای مبتنی بر دات نت باشد و تیم توسعه نیاز زیادی به ابزارهای دیگر احساس نخواهد کرد.
با اینحال این ابزار حداقل در برخی مواقع پاسخگوی نیازمندیها نیست و لازم است از ابزارهای تکمیلی استفاده شود یکی از این موارد استفاده از ماک آبجکتها (Mock Objects) است. استفاده از ماک (Mock Objects)
یکی از پارادایمهای اصلی توسعهی آزمون محور تاکید بر تمرکز و حذف وابستگیها است. بر اساس این توصیه، کد نویسی همواره متمرکز بر یکی از اجزای سیستم است، شما درحال نوشتن یک فرم در رابط کاربر هستید، پس روی آن تمرکز کنید و سایر بخشهای را فعلا از ذهنتان دور کنید. در عمل اما حفظ این استقلال بسیار مشکل است، به هر حال بخشهای مختلف سیستم با همدیگر مرتبط هستند، چگونه میتوان یک فرم در رابط کاربر را تست کرد در حالی که هنوز لایهی ارتباط با بانک اطلاعاتی شروع نشده است؟
در روش آزمون محور، تستها بایستی به شکلی مستقل و تقریبا همزمان قابل پیادهسازی باشند، این نکته کلید طراحی مناسب است و عدول از آن کلیات روش را به مخاطره میاندازد.
روشهای مختلفی برای حفظ این استقلال به هنگام نوشتن تستها مورد بررسی قرار گرفتهاند. این روش کارها را کانینگهام در اینجا و به شکلی منظمتر فاولر (Fowler) در اینجا بررسی کردهاند. به صورت کلی در این روشها وابستگی کامپوننت هدف از سایر اجزای سیستم با توسعهی اجزای بدلی (فاولر اصرار دارد این اصطلاح را از بدلکاران سینما وام گرفته شود) که در پروژهی تست نوشته میشوند، حذف میشود.
شما در حال توسعهی فرم رابط کاربر هستید، بسیار خب فعلا یک کلاس بنویسید که ارتباط شما با بانک اطلاعاتی را شبیه سازی کند و اطلاعات اولیه برای نمایش در فرم را در اختیارتان قرار دهد. اصطلاحا به این کلاس استاب (stub) گفته میشود. شما میتوانید برای اینکار از ابزارهای ماکینگ استفاده کنید که همین منظور را با امکانات بیشتری در اختیار شما قرار میدهند. تفاوت ماکینگ ئ استابها را "ماکها استاب نیستند" خیلی خوب توضیح داده است. به خصوص در مقالهای که میتوانید آنرا اینجا دریافت کنید، تاثیر توسعه بر اساس ماکها بسیار برجسته نشان داده شده است.
تفاوت اصلی ماکها در آنست که شما استابها را مینویسید، اما ماکها آبجکتهایی هستند که به هنگام اجرا توسط ابزار بر اساس اینترفیسها ساخته میشوند. در این روش شما یک اینترفیس جدید میسازید، آنرا به ابزار ماکینگ میدهید و این ابزار بر اساس آن یک آبجکت قابل استفاده تولید میکند. به این ترتیب شما در توسعهی کلاس مورد نظر نحوهی ارتباط آن با سایر کلاسها را از طریق توسعهی رابطهای مورد نظر تعریف میکنید. به این ترتیب به نظر میرسد خروجی کار تیمهایی که از این روش استفاده میکنند شامل تعداد به مراتب بیشتری از اینترفیسها خواهد بود که به صورت کلی تجربهی توسعهی بهتری محسوب میشود.
تفاوت اصلی دیگر آنست که آبجکتهای ماک میتوانند امکانات بسیار زیادی در خصوص تنظیم انتظارات شما از تست را در اختیار قرار دهند. در حالیکه روشهای دیگر آزمون صرفا بر اساس وضعیت نهایی آبجکتها و با دستوراتی مبتنی بر Assert ساخته میشوند، در ماک آبجکتها شما میتوانید اتظارات دقیقتری را برای تست در نظر بگیرید. مثلا فرض کنید تست شما آن باشد که در صورت اشکال در یکی از پارامترهای ورودی عملیات نویشتن صورت نگیرد. اینکار را بدون ماکها بایستی بر اساس نگهداری وضعیت آبجکت ( در این مثال اینکه آیا اطلاعات نوشته شده یا نه) در یک متغیر نگهداری کنید و آنرا در پایان تست بیازمایید. چیزی که توسعهی آزمون محور به شدت از آن اجتناب میشود، اینکه بخشی از کد محصول (در اینجا یک متغیر) صرفا برای تست به آن اضافه شود. بر اساس ابزارهای ماک شما میتوانید تستی ترتیب دهید که در صورت اجرای یک متد نامناسب خطا ایجاد شود. استفاده از NMock ویژوال استودیو برای استفاده از روش ماکینگ ابزار خاصی را ارائه نمیکند. به همین دلیل گروههای مختلفی این ابزار را برای استفاده در دات نت و بیشتر بر اساس نسخهای از این ابزار در جاوا (Jmock) توسعه دادهاند. یکی از این ابزارها Nmock است که به نظر میرسد به شکل قابل قبولی استفاده شده و مورد پذیرش قرار گرفته است. مثالهای این استفاده را میتوانید در MSDN و یا این مقالهی CodeProject ببینید.