تست نرم افزار چیست؟
تست نرم افزار فرآیند اجرای یک برنامه با هدف پیدا کردن اشکالات نرم افزاری است.
چرا تست نرم افزار ها امری ضروری است؟
معرفی تست واحد (Unit testing)
تست واحد، مجموعهای از تستها است که برای کوچکترین «واحد»های برنامه، یعنی متدها و کلاسها نوشته میشود. میخواهیم مطمئن شویم که همه اجزا یا واحدهای برنامه به درستی کار میکنند. مثلاً اگر متدی داریم که قرار است دو عدد را به عنوان پارامتر بگیرد و حاصل جمع آنها را به ما برگرداند، ما همواره تست میکنیم که ببینیم آیا این متد کاری که قرار است انجام دهد را به درستی انجام میدهد یا نه. بیشترین حجم تست برنامه، همین «تست واحد»ها هستند. نوشتن آنها بسیار ضروری اما بسیار ساده است. اگر همه تستهای واحد با موفقیت انجام شود، ما نمیتوانیم مطمئن شویم که برنامه به درستی کار میکند اما اگر یکی از آنها شکست بخورد، مطمئن میشویم که برنامه در اجرا به مشکل خواهد خورد.
مزایای تست واحد
کدام بخش نرم افزار بایستی تست شود
اینکه دقیقا می بایست چه بخش هایی تست شود، یک موضوع بسیار بحث برانگیز است. برخی از توسعه دهندگان بر این عقیده هستند که تمامی دستورات داخل کد می بایست مورد بررسی قرار گرفته و تست شود.
به هر حال شما بایستی برای بخش های پیچیده و حساس نرم افزار خود تست بنویسید. اگر ویژگی و قابلیت های جدید به اپلیکیشن خود اضافه نمایید، آنگاه یک مجموعه تست قدرتمند و کارامد می تواند اپلیکیشن شما را در برابر ضعف و خطاهایی که ممکن است بعدها به داخل اپلیکیشن و کد جاری راه پیدا کنند محافظت خواهد کرد.
در طراحی تست نرم افزاری می توان بخش های جزئی از کد را نادیده گرفت. برای مثال، نوشتن تست برای متدهای getter و setter که صرفا مقادیری را به فیلدهایی تخصیص می دهند، تقریبا بیهوده است. در واقع نوشتن تست برای تمامی دستورات داخل کد مشخصا بسیار زمان بر بوده و تقریبا امری بی فایده می باشد چرا که شما اپلیکیشن را در بستر JVM تست می کنید. JVM به خودی خود test case هایی از پیش تعریف شده و مشخص دارد.
در صورت طراحی تست برای بخش هایی از برنامه که قبلا تستی برای آن ها نوشته نشده، بهتر است ابتدا برای بخش هایی از کد، تست طراحی شود که دفعات رخداد خطا در گذشته در آن ها زیاد باشد. سپس می توانید بر روی بخش های اساسی کد متمرکز شوید.
آشنایی با فریم ورک JUnit
حالا دیگر با مفهوم تست واحد آشنا هستید. در اندروید برای تست واحد معمولاً از ابزارهای متنوعی استفاده میشود که معروفترین آنها JUnit است. JUnit چارچوبی ساده برای نوشتن تست است که نسخههای متعددی از آن برای زبانهای مختلف وجود دارد و J در ابتدای نام آن اشاره به زبان جاوا است.
کدهای تست را باید در کجا بنویسیم
برای این که بتوانیم برای برنامه تست بنویسیم و تستها را اجرا کنیم باید تغییراتی در برنامه بدهیم. اگر یک پروژه جدید ادر اندروید استودیو بسازید، به طور پیشفرض دو شاخه در ساختار پروژه میسازد:
شاخه androidTest همه تستهای UI در این شاخه قرار میگیرند.
شاخه test : تستهای واحد در این شاخه قرار دارند. این تستها در JVM یا همان ماشین مجازی جاوا اجرا میشوند و نیازی به دستگاه اندروید یا شبیهساز ندارند. در این تستها نمیتوانید از مؤلفههای اصلی اندروید مثل Activity یا Context استفاده کنید.
نحوه پیاده سازی تست در JUnit
می خواهیم نحوه ی استفاده از این توابع را در یک مثال ببینیم.فرض کنیم کلاسی داریم که عملیات ضرب و تقسیم را انجام می دهد. می خواهیم برای تست توابع این کلاس از JUnit استفاده کنیم. در ادامه کد کلاس آمده است :
اگر بخواهیم تابع تقسیم این کلاس را تست کنیم، می توانیم تابع تست زیر را بنویسیم . در این تابع ابتدا از کلاس مورد نظر یک نمونه ایجاد می کنیم(خط 13)سپس مقدار حاصل از تابع division را با مقدار مورد انتظارمان تطبیق می دهیم(خط 14).در ادامه هم بررسی می کنیم در صورتی که مخرج کسر صفر باشد خطای مورد انتظار ما رخ می دهد یا خیر ؟(خط 15 تا 20) برای این کار تابع division را با مخرج صفر اجرا می کنیم، اگر تابع درست عمل کند بعد از اجرای تابع برنامه باید وارد catch شود ، اگر این اتفاق نیفتد یعنی تابع درست عمل نکرده است پس به صورت دستی با فراخوانی تابع fail() تابع تست را fail می کنیم. در صورتی هم که واردcatch شود بررسی می کنیم نوع خطا همان نوع مد نظر ما است یا خیر ؟ تمام موارد توضیح داده شده را در کد زیر می بینید :
قرارداد روش های نام گذاری تست های مبتنی بر JUnit
قراردادهای نام گذاری متعددی برای تخصیص اسم به تست های طراحی شده بر اساس فریم ورک JUnit وجود دارد. یک راه حل پر طرفدار افزودن پسوند "-test" به اسم کلاس های تست (test case) و جایگذاری آن ها در پکیج جدید "test" می باشد.
به طور کلی، اسم تست باید درباره ی کاربرد و مورد استفاده ی آن توضیح دهد.در صورتی که اسم تخصیص داده شده به تست، مورد کاربرد آن را روشن بیان نماید، دیگر نیازی به خواندن پیاده سازی و محتوای کد نخواهد بود.
یک قرارداد ممکن و پرطرفدار استفاده از کلمه ی "should" در اسم متد تست می باشد. برای مثال، می توان به "ordersShouldBeCreated" یا "menuShouldGetActive" اشاره کرد. با این نوع انتخاب اسم برای متد، مشخص می شود که متد مورد نظر دقیقا چه رفتاری را تست کرده و انتظار چه نتیجه ای را دارد.
حاشیه نوشت ها(Annotations ) در JUnit
فریم ورک JUnit 4.x با استفاده از annotation های خود، متدهای تست را علامت گذاری کرده و امکان تنظیم اختصاصی آن ها را برای توسعه دهنده فراهم می آورد. جدول زیر لیستی از annotation های مهم در فریم ورک JUnit را به نمایش می گذارد.
دستورات Assert
دستورات assert معمولا با assert آغاز می شوند. متد assertion، خروجی واقعی تست را با مقدار مورد انتظار مقایسه می کند و چنانچه مقایسه با شکست مواجه شد، یک AssertionException صادر می کند.
جدول زیر این توابع را به صورت اجمالی همراه با شرح عملکرد هریک به نمایش می گذارد. پارامترهای ذکر شده در []، اختیاری بوده و از جنس String هستند.
برای یاد گیری بیشتر توصیه میکنم به این لینک مراجعه کنید.