منبع اصلی نوشتار زیر در این لینک قرار دارد

مقدمه ای بر TDD

مقدمه ای بر TDD

در سال ۱۹۹۹ گروهی از توسعه دهندگان متدولوژی eXtreme Programing  یا به اختصار XP را پدید آوردند. در این متدولوژی به جای آنکه ابتدا کد برنامه را نوشته و سپس آن را تست نمایند، برعکس عمل می­کردند. یعنی ابتدا کد تست را می­نوشتند، سپس کدهای برنامه را برای پاس کردن آن تست­ها اضافه می­کردند. به این شیوه، برنامه نویسی اول تست[۱] می­گفتند که به توسعه تست محور[۲] یا به اختصار TDD نیز معروف است. TDD حاصل تکامل فرآیند تولید نرم افزار است و بسیاری از مشکلات و چالشهای تولید نرم افزار را رفع می­کند. از این رو است که امروزه تبدیل به مهمترین سبک­ برنامه نویسی شده است. در ادامه اصول، مزایا و نحوه برنامه نویسی TDD بیان می­گردند.


[۱] Test-First Development

[2] Test Driven Development

سبک برنامه نویسی در TDD

TDD به عنوان یک سبک برنامه نویسی به طرز فریبنده­ای ساده است. بر عکس روش سنتی برنامه نویسی که شما می­نشستید و یک فرم یا کلاس ایجاد می­کردید، در TDD شما با نوشتن یک تست، کار را شروع می­کنید. با نوشتن یک تست در واقع یک نیازمندی را تعریف می­کنید. در حالی که شما مشغول تعریف تست­ها هستید، به یک نسخه اجرایی از نیازمندی­ها می­رسید. زمانی که این تست­ها پاس شوند، نیازمندی­ها نیز برآورده شده اند.

وقتی که شما اولین تست را می­نویسید، تست شما پاس (Pass) نمی­شود. اولین دلیل برای رد شدن تست (Fail) این است که برنامه کامپایل نمی­شود، زیرا کد تست کننده تلاش می­کند تا از کلاسی که هنوز تعریف نشده، نمونه گیری کند. فرض کنید می­خواهیم برنامه­ای بنویسیم که نتیجه یک عدد به توان عدد دیگر را محاسبه کند. کد تست این برنامه بدین صورت است[۱]:

۱
۲
۳
۴
۵
۶
۷
۸
۹
۱۰
۱۱
[TestFixture]
    public class PowerClassTest
    {
        [Test]
        public void PowerMethodTest()
        {
            var powerClass = new PowerClass();
            var result = powerClass.Power(2, 10);
            Assert.AreEqual(result, 1024);
        }
    }

در کد فوق PowerMethodTest() یک متد تست است. در این متد یک نمونه از کلاس PowerClass ایجاد شده و متد Power() با پایه ۲ و توان ۱۰ فراخوانی می­شود. سپس نتیجه این متد با مقدار مورد انتظار (۱۰۲۴) مقایسه می­شود. بنابراین این تست بررسی می­کند که آیا کلاس PowerClass به درستی عمل تقسیم را انجام می­دهد یا خیر.

مشخص است که این تست رد خواهد شد، چون اصلاً کلاس PowerClass و متد Power() تعریف نشده است. بنابراین آنها را تعریف می­کنیم.

۱
۲
۳
۴
۵
۶
۷
    public class PowerClass
{
    public int Power (int a , int b)
    {
 
    }
}

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

۱
۲
۳
۴
۵
۶
۷
۸
۹
۱۰
public class PowerClass
{
    public int Power (int a , int b)
    {
             int p = 1;
             for (int i = 1; i <= b; i++)
                p *= a;
             return p;           
    }
}

اکنون تست پاس می­شود، زیرا متد Power() با پارامترهای ۲ و ۱۰ مقدار ۱۰۲۴ را برگشت می­دهد که با مقدار مورد انتظار برابر است.  در این نقطه نیازمندی برنامه برآورده شده است.

همین که اولین تست پاس می­شود، باید تست­های بیشتری را اضافه کنیم و کدهای لازم برای پاس شدن آنها را بنویسیم. این چرخه آنقدر ادامه می­یابد تا تمامی نیازمندی­های برنامه برطرف شود. در ادامه مثالی واقعی از شیوه برنامه نویسی تست محور را بررسی خواهیم کرد.

مراحل TDD

همانطور که در مثال فوق مشاهده نمودید گردشکار TDD از دو گام تشکلیل شده است. در گام اول کد تست نوشته می­شود که نتیجه مطلوب برنامه را طلب می­کند. به این گام Red می­گویند به این خاطر که با اجرای تست، تست رد می­شود و نتیجه قرمز رنگ است. در گام دوم کدهای لازم برای برآورده شدن نتیجه مطلوب نوشته شده می­شود تا تست پاس شود. به این گام Green می­گویند، زیرا تست پاس شده است و نتیجه سبز رنگ است.

البته گام سومی هم وجود دارد که به آن Refactor می­گویند. در این گام کدهای برنامه بهبود می­یابند تا مطابق با اصول و قواعد طراحی باشند. البته عملکرد بیرونی کد نباید تغییر کند و باعث رد شدن تست قبلا پاس شده نشود.

\"tdd


[۱] برای نوشتن این تست از فریم ورک NUnit استفاده شده است که در فصل بعد به طور کامل تشریح می­گردد.


مزایای TDD

شاید به نظر برسد که روش TDD سربار زیادی در برنامه نویسی ایجاد می­کند و حجم کدها را دو برابر می­کند. زیرا باید برای هر نیازمندی، ابتدا کدهای تست نوشته می­شوند و پس از آن کدهای برنامه برای پاس کردن آنها ایجاد می­گردند. ولی باید بدانیم که TDD مزایای بسیار مهمی را فراهم می­کند که عبارتند از:

  1. کد کم حجم تر : کیفیت کد را از ابتدا تضمین می­کند. برنامه سازان فقط کدی را به برنامه اضافه می­کنند که تست ها را پاس کند و در نتیجه کد کمتر با احتمال خطای پایین تر خواهیم داشت.
  2. طراحی بهتر : چه از روی تفکر طراحی یا به عنوان اثر جانبی از TDD ، اکثر برنامه نویسان با سبک TDD قواعد SOLID را رعایت می­کنند.
  3. تطبیق کامل کد با نیازمندی بیزنس : وقتی که نیازمندی به صورت یک تست نوشته شود، کدی که آن تست را برآورده می­کند با احتمال بسیار زیاد آن نیازمندی را نیز براورده خواهد نمود.
  4. طراحی کتابخانه های ساده تر و متمرکز تر را فراهم می­کند. به خاطر اینکه برای اکثر کلاس­های برنامه Interface ساخته می­شود و شما اولین تست کننده کلاس خود هستید، توانایی طراحی کتابخانه مناسب را در شما به وجود می­اورد.
  5. تقویت ارتباط بین برنامه ساز و کاربر بیزنس : به خاطر اینکه تست ها بیان کننده نیازمندی های کاربر بیزنس است، وی می تواند در فرآیند توسعه نرم افزار شریک شود.
  6. کد های بدون استفاده را از برنامه بیرون نگه می­دارند. ممکن است برخی برنامه سازان کدهایی که احتمالا برای رفع نیازمندی های بعدی است را بنویسند که بعدا مورد نیاز نباشد با TDD چنین مشکلی پیش نمی آید.
  7. TDD امکان تست رگراسیون را فراهم می­کند. شما به محض نوشتن یک تست و پاس کردن آن می توانید کل تست ها را اجرا کنید تا مطمئن شوید که کد جدید اثر جانبی بر سایر بخشهای برنامه نداشته است.
  8. از برخورد با خطاهای تکراری پیشگیری می کند. وقتی که یک تست برای یک باگ ظاهر شده در برنامه می­نویسید، پس از هر بار اجرای تست­ها  می توانید مطمئن شوید که دیگر چنین باگی رخ نمی دهد.
  9. معماری  با کیفیت با امکان توسعه پذیری و تغییر پذیری  : هنگام برنامه سازی با تفکر تست گر در انتهای برنامه ای که با کمک DI مستحکم است به راحتی قابل تغییر است، و نسبت به خطاها مقاوم است.

توسعه رفتار محور (BDD)

یکی از مشکلات TDD این است که تست­ها تنها برای توسعه دهندگان قابل درک است و افراد بیزنس نمی­توانند از آن سر در بیاورند. همانطور که قبلا بیان شد هر تست بیانگر یک نیازمندی است که با پاس شدنش، آن نیازمندی برطرف می­شود. بنابراین اگر تست­ها برای افراد بیزنس قابل درک باشند، می­توانیم از آنها برای طراحی و نظارت بر تست­ها استفاده کنیم.

برای رسیدن به این هدف روش توسعه مبتنی بر رفتار (Behavior Driven Development) مطرح شده است. BDD یکی از مشتقات TDD است که بر اساس همکاری نزدیک تیم توسعه و تیم بیزنس برای ساخت نرم افزار با کیفیت عمل می­نماید. در BDD به جای عبارت تست از مشخصه (Specification) استفاده می­گردد. این روش توسعه از الگوریتم زیر پیروی می کند :

  1. نیازمندی­های بیزنس به شکل رفتارهای نرم افزار تعریف می­گردند و هر رفتار به مجموعه­ای از مشخصه­های قابل اجرا تبدیل می­شوند. مشخصه­ها به زبان بیزنس بوده و برای همه قابل فهم است.
  2. کدهای مناسب برای پاس کردن مشخصه­ها نوشته می­شوند.
  3. با اعمال قواعد Refactoring کدهای برآورده کننده مشخصه­ها بهینه می­شوند.
  4. هر تغییر یا نیازمندی جدید به صورت یک رفتار در نرم افزار ثبت شده و مراحل فوق برای آن تکرار می­شود.

منبع: agiledevelopment



برچسب ها : , , , ,