آموزش Unit Testing در زبان برنامه‌نویسی سی‌شارپ
آموزش Unit Testing در زبان برنامه‌نویسی سی‌شارپ » در این مقاله، Unit Test را معرفی کرده و به ذکر چند مثال کاربردی و نحوه رفع خطاهای آنها خواهیم پرداخت.

آموزش Unit Testing در سی‌شارپ

Unit Testing Tutorial in C-Sharp

unit testing

 

 Unit Testing چیست و چه کاربردی دارد؟ 

 

لزوم استفاده از Unit Testing :

فرض کنید پروژه ای  طراحی و پیاده سازی شده است ، اکنون به مرحله تست کردن میرسد . شرکت سازنده پروژه (اپلیکیشن تحت وب) به یک برنامه نویس خبره میگوید این برنامه تحت وب را تست کند . بعنوان مثال این برنامه نویس بعد از یک هفته می گوید این پروژه را تست کردم . در صورتی که ممکن است آنرا تست نکرده باشد و حتی در صورت تست کردن ، نداند و یا فراموش کند کدام بخشهای پروژه را تست کرده است .

حالا فرض کنید چند ماه بعد این پروژه توسعه داده می شود و یا تغییراتی در سیستم حال حاضر اعمال می شود . دوباره نوبت به تست آن میرسد . پس از رایزنی با برنامه نویس مذکور ، ایشان ۱۰ تا تست روی سیستم جدید انجام می دهد و دوباره نمی آید ۱۰۰ تا تست قبلی را نیز انجام دهد ( یا تست های قبلی را بخاطر ندارد و یا تنبلی می کند !)

رده بندی بخشها و افراد در سازمانها و شرکت های برنامه نویسی بزرگ دنیا (از لحاظ خبره بودن) بصورت زیر است :

  1. مدیر پروژه
  2. مدیر فنی
  3. تستر (فردی که سیستم را تست میکند)
  4. کارشناس درجه ۱
  5. کارشناس درجه ۲ و …..

 

بنابراین مشاهده می شود که فرد Tester باید خبره باشد و یا به قول معروف کار بلد و حرفه ای باشد زیرا خطاهایی که فرد حرفه ای پس از تست سیستم از پروژه بیرون میکشد بیشتر و حیاتی تر از هنگامیست که فردی آماتور اینکار را انجام دهد .

 

مزیت Unit Testing :

اجازه می دهد که کد سی شارپی را بنویسید که کدهای سی شارپ (C#) پروژه شما را تست کند .

در صورت استفاده از Unit Testing ، این امکان وجود ندارد که فرد تستر به دروغ به آن شرکت بگوید که سیستم شما را تست کردم . زیرا مدارکی مبنی بر تست سیستم را از تستر می خواهد . و دیگر اینکه مشخص است کدام بخشهای پروژه را تست کرده ایم و یادمان نمیرود . و در نهایت اگر ۶ ماه دیگه ، پروژه دچار تغییراتی شود ، دیگر نیازی نیست تمام آن ۱۰۰ تست قبلی را نیز روی سیستم انجام دهیم . بلکه فقط کافیست مثلا ۱۰ تا تست مربوط به این تغییرات جدید را بنویسیم و اجرا کنیم . خود Unit Testing تمام ۱۱۰ تست را اجرا میکند .

 

پلتفرم‌های پیاده‌سازی Unit Testing:

آموزش هایی که در زمینه Unit Testing وجود دارد (چه بصورت فیلم چه کتاب)  اکثرا روی معماریهای مدرن مانند MVC  و یا MVVM پیاده سازی شده است . بنابراین این تصور اشتباه شکل میگیرد که قابلیت Unit Testing  فقط برای معماری های مدرن طراحی شده است . در صورتی که ما در این آموزش میخواهیم این قابلیت را روی بستر Windows Form پیاده سازی کنیم و آموزش دهیم .

نکته : شایان ذکر است که این قابلیت روی معماریهای مدرن که لایه بندی شده می باشد بهتر کار میکند . یعنی معماری هایی در آنها View با c# code و Business مجزا می باشند و مانند ASP.NET webform همه عناصر برنامه و وب سایت در دل هم نوشته نشده اند .

مبحث Unit Testing در دنیای برنامه نویسی تا حدی جدی و گسترده شده که در پروژه های حرفه ای و سنگین ، ابتدا تست برنامه نوشته می شود و سپس کد برنامه (TestFirst Pattern) . در صورتی که معمولا بدین گونه است که ابتدا برنامه نوشته شود و سپس تست آن انجام شود .

در بخش بعد، از فضای تئوری خارج می شویم و با هم یک پروژه جدید ایجاد خواهیم کرد و unit testing را عملا شروع می کنیم . با ما باشید.

 

شروع کار با Unit Testing

 

ساخت یک پروژه Windows-Form در ویژوال استودیو:

برنامه ویژوال استودیو را باز کنید و یک پروژه Windows Form Application بنام UnitTestingApp ایجاد کنید . مانند شکل زیر:

 

windows-form-application

 

کلاس‌ها و توابع موردنیاز پروژه:

سناریو : در این پروژه ، یک کلاس Utility ایجاد میکنیم که یک تابع (function) دارد . این تابع یک رشته (string) را بعنوان ورودی می گیرد و آنرا fix می کند (یعنی فاصله های اضافه را حذف کند و آنرا مرتب کند)

در این مثال میخواهیم از الگوی test first پیروی کنیم . یعنی اول توقعاتمان را از پروژه اعلام میکنیم و سپس قدم به قدم شروع به توسعه دادن برنامه می کنیم . و در این حین تست خود را اجرا میکنیم تا ببینیم انتظارات ما برآورده شده است یا خیر .

تعریف کلاس Utility:

پس از باز کردن ویژوال استودیو ، روی نام پروژه راست کلیک کرده و Add -> Class را انتخاب می کنیم . نام کلاس را Utility.cs قرار میدهیم . در این کلاس ، یک تابع بنام FixText تعریف میکنیم که ورودی آن یک رشته است و خروجی آن نیز یک string یا رشته است . کد کلاس Utility بصورت زیر می باشد :

 
namespace UnitTestingApp
{
    public static class Utility
    {
        static Utility() { }
        public static string FixText(string text)
        {
            return (text);
        }
    }
}
                                 

قبل از اینکه این کلاس را توسعه دهیم ، میخواهیم به تستر بگوییم انتظار ما از این پروژه چیست . بنابراین برای افزودن تستر ، روی solution راست کلیک کرده و add new project را میزنیم .

در پنجره باز شده ، در لیست انتخابی سمت چپ ، Test را انتخاب کرده و در سمت راست ، گزینه Unit Test Project را انتخاب کنید (مانند شکل زیر) :

 

new-unittest-project

 

در بخش بعد، پروژه قبلی یعنی UnitTesingApp را به پروژه unit test اضافه خواهیم کرد و شروع به نوشتن کدهای لازم می کنیم . همراه ما باشید.

 

افزودن رفرنس پروژه اول به پروژه تست

 

چون پروژه جدید یعنی (UnitTestProject) قرار است پروژه قبلی یعنی (UnitTestingApp) را تست کند ، باید رفرنس پروژه اول را به پروژه تست اضافه کنیم . بنابراین در زیرشاخه پروژه تست ، روی فولدر References راست کلیک کرده و add Reference… را انتخاب می کنیم .

مطابق تصویر زیر در پنجره باز شده ، در حالی که در سمت چپ ، Solutions در حالت انتخاب است ، در سمت راست ، تیک گزینه موجود را بزنید :

 

افزودن رفرنس پروژه

 

کلاس UnitTest :

مشاهده می شود که در زیرمجموعه پروژه تست ، یک کلاس بطور پیش فرض بنام UnitTest1.cs ایجاد شده است . کلاس هایی که میخواهیم کار تست را انجام دهند باید اتریبیوت [TestClass] را داشته باشند . در این کلاس میتوانید چند تابع تعریف کنید که کار تست را انجام دهند .

نکته : تابعی تست پذیر است که دارای اتریبیوت [TestMethod] باشد :

 

کلاس Unit Test

 

کلاس Assert :

در بدنه این تابع ، باید کلاسی بنام Assert را پیاده سازی کنیم . در واقع کار اصلی تست کردن را این کلاس  انجام می دهد . این کلاس بصورت استاتیک (static) تعریف شده است . بنابراین برای استفاده از آن نیازی نیست از آن شئ بسازیم . بلکه بصورت تصویر زیر مستقیما نام کلاس را نوشته و سپس نقطه (.) میزنیم و متدهای آن کلاس نمایش داده می شود (مانند AreEqual , AreSame , IsNull , IsTrue , …)

همانطور که در تصویر زیر مشاهده می کنید ، این کلاس دو پارامتر expected , actual می پذیرد که پارامتر expected مقداری که انتظار میرود است و پارامتر actual مقدار واقعی بدست آمده می باشد.

 

کلاس Assert

 

تعریف TestMethod1 :

تا بدین جا کدهای زیر را در متد TestMethod1 تعریف کنید :

 
public void TestMethod1()
{
    string strSource = null;
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: string.Empty, actual: strActual);
}
                                 

تعریف کلی تست : میخواهیم بررسی کنیم که با مقدار ورودی strSource ، آن چیزی که بدست می آید (actual) با آن چیزی که من انتظار دارم (expected) برابر است یا نه .

نکته : مقدار expected را کسی که از سیستم مطلع است و بر آن مسلط است میتواند اعلام کند .

در مثال فوق ، میخواهیم اگر رشته ورودی (strSource) برابر null بود ، null String (string.Empty) تحویل بگیریم .

 

تعریف TestMethod2 :

میخواهیم اگر ورودی بصورت null string بود ، خروجی نیز null string باشد (string.Empty) :

 
[TestMethod]
public void TestMethod2()
{
    string strSource = "";
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: string.Empty, actual: strActual);
}
                                 

 

تعریف TestMethod3 :

میخواهیم اگر ورودی رشته تابع FixText دارای space بود ، مجددا خروجی null string (یعنی string.Empty) باشد :

 
[TestMethod]
public void TestMethod3()
{
    string strSource = "   ";
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: string.Empty, actual: strActual);
}
                                 

 

تعریف TestMethod4 :

میخواهیم اگر ورودی برابر Ehsan Safari بود ، خروجی آن برابر Web Developer باشد :

 
[TestMethod]
public void TestMethod4()
{
    string strSource = "Ehsan Safari";
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: "Web Developer", actual: strActual);
}
                                 

 

تعریف TestMethod5 :

میخواهیم اگر ورودی برابر Ehsan Safari بهمراه چندین  space در اطرافش بود ، خروجی آن برابر Ehsan Safari  باشد :

 
[TestMethod]
public void TestMethod5()
{
    string strSource = "    Ehsan Safari        ";
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: "Ehsan Safari", actual: strActual);
}
                                 

 

تعریف TestMethod6 :

میخواهیم اگر بین Ehsan و Safari دو یا چند space وجود داشت ، در خروجی فقط یک space بین این دو کلمه باشد :

 
[TestMethod]
public void TestMethod6()
{
    string strSource = "Ehsan      Safari";
    string strActual = UnitTestingApp.Utility.FixText(strSource);
    Assert.AreEqual(expected: "Ehsan Safari", actual: strActual);
}
                                 

پروژه هنوز develop نشده است . در کلاس Utility ما فقط یک رشته بصورت ورودی گرفتیم و برگرداندیم . در بخش نهایی این آموزش میخواهیم تست تعریف شده خود را run کنیم و ببینیم شرایط تا بدین جا چگونه است . پس با ما باشید …laugh

 

 اجرای متدهای تست پروژه 

 

بدین منظور ، هنگامی که کلاس UnitTest1.cs باز است ، روی نام کلاس UnitTest1 راست کلیک کنید (مطابق شکل زیر) و Run Tests را بزنید :

 

run test

و نتیجه اجرای تست بصورت زیر می باشد :

نتیجه اجرای تست

 

 رفع خطاهای متدهای تست 

 

برای رفع خطای تست متداول ، باید یک شرط if در تابع FixText تعریف کنیم مبنی بر اینکه اگر رشته ورودی null بود خروجی را برابر  string.Empty  قرار بده :

 
    if(text == null)
    {
        return (string.Empty);
    }
                                 

اکنون با زدن دکمه Run All در تصویر فوق ، مشاهده می شود که TestMethod1 نیز پاس شد .

رفع خطای تست ۴ :

باید شرطی بگذاریم که اگر رشته ورودی برابر Ehsan Safari بود ، عبارت Web Developer به خروجی برود :

 
if (text == "Ehsan Safari")
{
    return ("Web Developer");
}
                                 

رفع خطای تست ۶ :

بدین منظور ، باید در یک حلقه while ، تا زمانی که در رشته ورودی ، دو تا space میبیند آنرا با یک space جایگزین کند :

 
while (text.Contains("  "))
{
    text = text.Replace("  "," ");
}
                                 

رفع خطای تست ۳ :

برای حذف فضاهای خالی اضافی رشته (space) از دستور Trim استفاده می کنیم . بنابراین اگر دستور زیر را بنویسیم ، دو تست ۳ و ۵ نیز پاس می شوند زیرا مربوط به خالی نبودن فضای اطراف رشته هستند :

text = text.Trim();

با اعمال این تغییرات در تابع FixText ، به نتیجه ای برابر تصویر زیر خواهیم رسید :

 

نتیجه تست نهایی

 

نتیجه گیری : Unit Testing یعنی خلق کلاس هایی که کلاس های سی شارپ ما را تست می کنند .

» برای تکمیل دانش خود در زمینه Unit-Testing مقاله "Unit Test Basics" را از سایت مایکرو سافت مطالعه نمائید.

امیدوارم این مقاله مورد استفاده شما عزیزان قرار گرفته باشد. از طریق لینک زیر می توانید سورس کد این مقاله را دانلود کنید:

 

دانلود سورس کد آموزش Unit Testing

 

لطفا نظرات و سوالات خود را درباره این مقاله به ایمیل EhsanSafari@hotmail.com ارسال نمایید .


برچسب‌ها:

test methodunit testingآموزش unit testآموزش unit testingخطاهای تست متدرفع خطاهای تستمتد تستیونیت تستیونیت تستینگ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

6 + 3 =