اگر تجربه کار در زمینه نرم افزار های پیچیده را داشته باشید، حتما به واژه تست نرم افزار بر خورده اید. اگر هم ایده ای درباره تست نرم افزار ندارید لطفا مقاله زیر را مطالعه کنید تا با این مبحث بسیار مهم آشنا شوید.
آشنایی با تست نرم افزار
همانطور که می دانید، تست نرم افزار از سطوح مختلفی تشکیل شده است که هرم تست را تشکیل می دهند.
یکی از مهمترین بخش های هرم تست، unit test است. اگر به هرم تست نگاهی بیاندازید متوجه خواهید شد که unit testing در قاعده این هرم قرار گرفته است. آیا تا به حال به معنای آن دقت کرده اید؟ به نظرتان این جایگاه چه پیامی را به همراه دارد؟
حال اجازه دهید کمی به عقب برگشته و به معنی و مفهوم unit test بپردازیم:
Unit testing روشی برای انجام تست بر روی کوچکترین قطعه کد بدون در نظر گرفتن وابستگی (Dependency) های آن است. در حقیقت هدف از اینگونه تست اطمینان از صحت عملکرد سیستم مورد نظر (System Under Test SUT) به همان طریقی که ما از آن انتظار داریم است. ما به وسیله unit testing می توانیم تست کنیم که آیا SUT ما فارق از هرگونه وابستگی و اصطلاحا در Isolation، آنگونه که انتظار داریم عمل می کند یا نه.
همانگونه که در این تعریف آمده است، unit testing سیستم را بدون درنظر گرفتن وابستگی های خارجی آن تست می کند. از این تعریف اینگونه استنباط می شود که این دسته از تست ها فقط و فقط در Memory اجرا می شوند و هیچ کاری به محیط اطراف خود ندارند.
بنابراین مهمترین نکته این است که unit test ها بسیار سریع هستند، زیرا در Memory اجرا می شوند. همیطور به دلیل عدم ارتباط با دیتابیس، فایل یا هر گونه API خارجی، هیچ اثری روی محیط اجرای تست ندارند و نیازی نیست تا پس از اجرای آنها، عملیات Teardown انجام گیرد.
پس Unit Testing بسیار کم هزینه است! زیرا ما تلاش کمتری برای نوشتن این دسته از تست ها انجام می دهیم همچنین تعداد خط کد کمتری نیز می نویسیم.
بر می گردیم به سوال بالا:
آیا تا به حال به این موضوع دقت کرده اید که چرا Unit Test ها قاعده هرم تست را به خود اختصاص داده اند؟
پاسخ این سوال بسیار ساده است. به دلیل سرعت بالا و هزینه کم پیاده سازی Unit Testing، جایگاه این دسته از تست ها در هرم تست، قاعده آن است. بدان معنا که چگالی تست های unit در میان دیگر انواع تست باید بیشتر باشد. در حقیقت باید تعداد بیشتری unit test نسبت به دیگر انواع تست ها (integration, acceptance) داشته باشیم.
به عنوان مثال اگر در یک پروژه به طور کلی 2000 تست وجود داشته باشد، عمده این تعداد را باید Unit Test ها تشکیل دهند و میزان Acceptance Test ها باید کمتر از همه باشد. زیرا Acceptance Test ها در راس هرم تست قرار دارند.
یک مثال از Unit Test
برای تمرین تست نویسی می توانید از مثال های Test Kata استفاده کنید. در این مثال ما از تمرین EvenOrOdd استفاده می کنیم.
فرض کنید کلاسی به نام Evaluator داریم. در این کلاس متدی به نام Evaluate وجود دارد که قرار است یک عدد را دریافت کرده، زوج یا فرد بودن آن را تشخیص دهد.
اگر عدد زوج بود واژه “Even” و اگر عدد فرد بود واژه “Odd” را به عنوان خروجی متد برگرداند. کد پیاده سازی این مثال به شکل زیر است:
حال قصد داریم که برای این کد Unit Test بنویسیم. دقت کنید که متد Evaluate هیچگونه وابستگی خارجی نداشته و همه کارها را درون Memory انجام می دهد.
نکته: در این مثال ما از XUnit برای نوشتن تست ها استفاده می کنیم. این ابزار Test Framework ما خواهد بود. برای نصب آن کافی است دستور زیر را اجرا کنید:
Install-package xunit
سپس باید کتابخانه xunit.runner.visualstudio را نیز برای اجرا شدن تست ها روی Visual Studio نصب کنید. این ابزار Test Runner ما خواهد بود. برای نصب آن کافی است دستور زیر را اجرا کنید:
Install-package xunit.runner.visualstudio
همچنین می توانید این کتابخانه ها را از Nuget دانلود کرده و به پروژه تست خود اضافه کنید.
برای آنکه بتوانیم برای متد Evaluate تست بنویسیم، باید حالات مختلف آن را بررسی کنیم تا مشخص شود که این متد به ازای کدام ورودی ها، چه رفتاری از خود نشان می دهد و اصطلاحا چند مسیر اجرا (Execution Path) دارد. سپس برای هر یک از این حالات، تست های جداگانه بنوسیم.
در این مثال ساده، برای متد Evaluate، دو مسیر اجرا وجود دارد.
مسیر اول: اگر عدد ورودی زوج باشد واژه “Even” باز گردانده می شود و تست این مسیر به شکل زیر انجام می شود:
در این Unit Test یک مقدار زوج (عدد 6) به متد Evaluate پاس داده شده و از این متد انتظار داریم که واژه “Even” را به عنوان خروجی باز گرداند که این اتفاق با موفقیت انجام شده است.
مسیر دوم: اگر عدد ورودی فرد باشد واژه “Odd” باز گردانده می شود و تست این مسیر به شکل زیر انجام می شود:
در این Unit Test یک مقدار فرد (عدد 11) به متد Evaluate پاس داده شده و از این متد انتظار داریم که واژه “Odd” را به عنوان خروجی باز گرداند که این اتفاق هم با موفقیت رخ داده است.