Unit Testing چیست + کاربردها و مشکلات آن
یونیت تستینگ Unit Testing یا تست واحد یکی از فرآیندهای توسعه نرم افزار است که در آن کوچکترین اجزای قابل آزمایش یک اپلیکیشن (Unit) به منظور اطمینان از عملکرد مناسب به صورت جداگانه مورد آزمایش قرار می گیرند. این فرآیند یکی از مهم ترین مباحث حوزه برنامه نویسی محسوب می شود که در ادامه آن را به صورت عمیق بررسی خواهیم کرد.
Unit Testing چیست؟
یونیت تست (Unit Test) به معنای آزمایش کوچکترین قطعه کدهایی است که قابلیت جداسازی منطقی در یک سیستم را دارند و در اکثر زبان های برنامه نویسی به عنوان یک تابع، زیر روال (Subroutine)، دارایی یا متد محسوب می شود. مایکل فزرث، نویسنده حوزه نرم افزار در یکی از کتاب های خود درباره یونیت تستینگ چنین می گوید: تست هایی که به سیستم های خارجی متکی هستند را نمی توان به عنوان یونیت تست در نظر گرفت؛ به عبارت دیگر اگر تستی در دیتابیس یا شبکه انجام شوى، آنگاه به سیستم فایل دسترسی پیدا کرده و مستلزم کانفیگ سیستم است و در غیر اینصورت قابلیت اجرای همزمان با تست های دیگر امکان پذیر نخواهد بود.
Unit Test های امروزی و مدرن را می توان در فریم ورک هایی نظیر JUnit یا با استفاده از ابزارهای تستینگ مانند TestComplete اجرا کرد. البته اولین فریم ورک برای اجرای تستینگ توسط کنت بِک طراحی شد و قبل از آن هیچ ردپایی از یونیت تستینگ در توسعه اپلیکیشن دیده نمی شود.
البته افرادی مانند Jerry Weinberg اعتقاد دارند که استفاده از Unit Testing از زمان پیدایش سیستم های کامپیوتری همواره توسط برنامه نویسان انجام شده است. صرف نظر از اینکه یونیت تستینگ در کجا و چه زمانی ظهور کرده است، جنبه های کاربردی این روش را در ادامه با یکدیگر مرور خواهیم کرد.
یونیت تستینگ چه شکلی دارد؟
یونیت یا همان واحد تقریبا می تواند هر چیزی باشد. برای مثال یک خط کد، یک متد یا کلاس را می توان به عنوان یک یونیت در نظر گرفت. هر چقدر که یونیت کوچکتر باشد بهتر است چرا که تست های کوچک نمای دقیق تری از نحوه عملکرد کدها را در اختیار شما قرار می دهند. البته کوچک بودن یونیت باعث می شود که زمان انجام تست نیز بسیار کاهش یابد (برای مثال انجام هزار تست در ثانیه).
کد زیر را در نظر بگیرید:
1 2 3 4 5 |
def divider (a, b) return a/b end |
تست های کوچک در زبان روبی (Ruby) به شکل زیر خواهند بود:
1 |
class smallTest < MiniTest::Unit::testCase def tiny_test @a=9 @b=3 assert_equal(3, divider(a, b)) endend |
مثال بالا یک نمونه بسیار ساده است اما منظور ما از کوچک بودن یونیت را به خوبی منتقل می کند. تست های کوچک همچنین عبور از سیستم ها را دشوار خواهد کرد؛ برای مثال رد شدن از یک کد و ورود به یک دیتابیس یا سیستم های دیگر دشوار می شود. این موضوع مشکل چندانی به وجود نمی آورد اما کاهش تدریجی سرعت تست یکی از عواقب آن است.
چه کسانی باید Unit test را بسازند؟
رابرت هد در کتاب خود به نام Real Time Business Systems برنامه نویس را مسئول اجرای یونیت تستینگ معرفی می کند. در حقیقت برنامه نویس از نحوه دسترسی به یونیت هایی که به راحتی قابل آزمایش هستند باخبر است. علاوه بر این برنامه نویس اجزایی که غیر قابل دسترسی هستند را نیز به طور دیگری آزمایش می کند. در برخی اوقات نیز یک فرد دیگر پس از طراحی اپلیکیشن به پروژه اضافه شده و در حالی که بخشی از پایگاه کد را توسعه یا ریفکتور (Refactor) می کند، تست هایی برای برقراری امنیت اپلیکیشن نیز طراحی خواهد کرد.
ابزارهای رایج برای Unit testing
- NUnit : فریم ورکی متن باز برای تکنولوژی .Net است.
- Junit : ابزاری رایگان برای پیاده سازی Unit Test در جاوا است.
- EMMA : ابزاری نوشته شده به زبان جاوا برای آنالیز و گزارش گیری است.
- JMockit : ابزار عمومی Unit Testing با قابلیت های بسیار کاربردی
- PHPUnit : به کمک PHPUnit می توان در زبان محبوب PHP یونیت تستینگ را انجام داد.
یونیت تست چه کاربردهایی دارد؟
چکش یک ابزار بسیار کاربردی است که می توان کارهای بسیاری نظیر شکستن اجسام سخت یا باز کردن پنجره خودرو را با آن انجام داد اما کاربرد اصلی آن در کوبیدن میخ است. یونیت تستینگ نیز مشابه چکش است به گونه ای که قابلیت های متعددی دارد اما باید در زمینه ای خاص مورد استفاده قرار بگیرد. در ادامه چند مورد از مهم ترین کاربردهای یونیت تستینگ را بررسی خواهیم کرد.
1- برنامه نویسی تست محور
برنامه نویسی تست محور (TDD) یک تکنیک طراحی کد است که در آن برنامه نویس قبل از هر چیز، ابتدا تست های مربوطه را طراحی کرده و سپس کدهای یک نرم افزار را می نویسد. هدف اصلی روش تست محور این است که برنامه نویس با اطمینان از آزمون های اولیه قادر خواهد بود به صورت آزادانه ریفکتورهای بیشتری انجام داده و در نهایت کدهای تمیزتری بنویسد.
ایده و هدف این روش بسیار ساده است ولی همانند اغلب کارهای ساده، اجرای آن بسیار دشوار خواهد بود. یادگیری برنامه نویسی تست محور سخت و مستلزم یک ذهنیت کاملا متفاوت است، بنابراین در ابتدای راه سرعت برنامه نویس را کاهش خواهد داد.
2- بررسی کار
برنامه نویسی TDD یک روش جدید نیست ولی هنوز بهترین گزینه برای برنامه نویسان جاه طلب به شمار می رود. دیگر توسعه دهندگان نیز خودشان کار را بررسی می کنند. طراحی یونیت تست قبل از نوشتن کدها را می توان به عنوان یکی از روش های سنتی بررسی کار قلمداد کرد. علاوه بر این روش های مبتنی بر ریاضیات نیز برای انجام این کار مورد استفاده قرار می گیرند.
بعد از اجرای تست و اطمینان از نحوه عملکرد کدها، کمیت یونیت تست کمی دچار تغییر خواهد شد. تست هایی که به راحتی با هر ساختاری از یک محصول سازگار هستند، تغییرات غیرمنتظره را شناسایی کرده و به برنامه نویسان اعلام می کنند.
3- مستند سازی کد
مستندسازی کدها (Code Documentation) نشان دهنده چگونگی نگارش کدهای کوچک است. یونیت تستینگ با ترغیب برنامه نویسان به استفاده از روش های بهتر کدنویسی و اعمال کدهایی که عملکرد نرم افزار را توصیف می کنند، در واقع فرآیند مستندسازی کدها را بسیار آسان خواهد کرد. به عبارت دیگر به جای اینکه هر گونه تغییر کوچک در کدها را در حجم عظیمی از مستندات اعمال کنید، یونیت تستینگ یک سیستم بررسی در اختیار شما قرار می دهد که می توانید با هر بار تغییر، آن را بروزرسانی کنید.
4- محدوده خطر
یونیت تستینگ همچنین کاربردهایی دارد که برنامه نویسان از آنها جلوگیری می کنند. ساخت آزمون های یکپارچه برای عبور از مرز سیستم ها و دسترسی به دیتابیس یا سیستم های ثالث دیگر باعث به وجود آمدن سلسله تست هایی می شود که اجرای آنها زمان بسیار زیادی را می طلبد. البته چهارچوب های بسیاری از آزمون فوق تخصصی وجود دارند که برای اجرای تست های همزمان در بخش های بزرگتر یک اپلیکیشن مورد استفاده برنامه نویسان قرار می گیرند.
تست های End-to-End نیز یکی دیگر از بخش های ریسکی و پرخطر محسوب می شود. این نوع از تست ها مستلزم مرتب سازی، تنظیمات دقیق و اجرای آزمون های دیگر هستند. به عبارت دیگر سیستم مورد نظر باید برای اجرای تست در حالت آماده باش قرار گیرد. تقریباً شبیه به تست های یکپارچه، ابزارهای زیادی وجود دارند که فقط با هدف اجرای آزمون های End-to-End طراحی شده اند. شما می توانید این کار را با Unit Testing نیز انجام دهید اما باید زمان زیادی را برای اجرای آن صرف کنید.
مشکلات رایج Unit Testing
مشکلاتی که در اجرای یونیت تست ها با آن مواجه می شویم اغلب مشکلات فنی نیستند. در حقیقت مشکل اصلی مربوط به سازگاری برنامه نویسان با یونیت تستینگ است. برخی از افراد معتقدند که اگر تستینگ خوب است بنابراین اجرای تعداد بیشتری از آن نیز باید مزیت های بیشتری داشته باشد. آزمون های هوشمند (Smart Testing) نیز گزینه خوبی هستند و در ساخت محصولات نرم افزاری پایدار و با ارزش به برنامه نویسان کمک می کنند، البته این تست مستلزم اجرای آزمون های نامحدودی خواهد بود. به طور کل آزمون هوشمند، اطلاعات مربوط به نرم افزار را به سرعت در اختیار برنامه نویسان قرار می دهد.
یکی دیگر از مشکلات یونیت تست ها عدم توانایی آنها در شناسایی تمامی باگ ها و نواقص موجود در نرم افزار است و به هیچ وجه نباید به عنوان تنها روش آزمایش کدها مورد استفاده قرار بگیرد. همچنین از آنجایی که Unit testing بر روی بخش های کوچک برنامه متمرکز است، نمی تواند گزینه مناسبی برای تست کامل نرم افزار باشد.
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.