What is TDD? Why should I use TDD?

Test Driven Development cycle
Test Driven Development cycle


درود به همگی

امروز اومدم در مورد توسعه مبتی بر آزمون یا همون Test-driven developmentصحبت کنم. تا همین شاید دوماه پیش خودم هم نمی دونستم که TDD چی هست؟ یا همچین تکنولوژی وجود داره و اصلا واسه چی خوبه! اما خب برای پروژه شرکت و به الزام مدیرفنی شرکت به سراغش رفتم.

حالا می خوام آنچه که تا امروز مطالعه کردم رو با شما به اشتراک بزارم.

بزارید قبل از اینکه درخصوص TDD و چرایی استفاده از این تکنولوژی بگم در خصوص Unit Testها کمی صحبت کنم.

آزمون واحد نوع خیلی خاصی از تست نرم‌افزار، با اهداف و مجموعه ویژگی‌های خیلی روشن است. خوشبختانه تعریف اولیه آزمون واحد، نسبتاً خیلی ساده است: Unit Test یک تست است که یک نیاز مشخص برای یک متد مشخص را آزمایش می‌کند. پس اگر تست شما،‌ قانون یک نیاز/یک متد را نقض کند، همچنان یک تست است اما دیگر unit test نیست.
آزمون‌های واحد که قانون یک نیاز/یک متد را رعایت می‌کنند، ویژگی‌های زیر را هم به عنوان یک unit test‌ دارند:

  • هدفمند باشه: منظور تستی که برای یک متد در نظر می گیریم هدفی را دنبال کنه و هدف مشخصی را تست کنه.
  • ایزوله باشه: کدی که در حال تست آن هستید باید از کد اصلی برنامه و وابستگی‌های خارجی یا رویدادها جدا بوده و ایزوله شده باشد.
  • قابل تکرار و قابل پیش‌بینی باشه: یک آزمون واحد باید قابلیت بارها تکرار مجدد را داشته باشد (Repeatable باشد) و با فرض اینکه کد در حال تست و خود تست تغییر نکنند، هر دفعه همان نتیجه را تولید کند (قابل پیش‌بینی یا Predictable باشد)
  • مستقل باشه: این تست‌ها باید مستقل باشد، به صورت کلی هیچ تضمینی در خصوص ترتیب اجرا unit test ها وجود ندارد و بنابراین تست‌های نوشته شده توسط شما نباید انتظار یا نیاز به این مساله داشته باشند.

اولین D در TDD مخفف Driven هست.
ایده این روش این است که اولین کاری که برنامه‌نویس انجام می‌دهد نوشتن تست بر اساس ویژگی مورد انتظار فعلی نرم‌افزار (specification) است که روی آن کار می‌کند.پس بهتر بگیم، کار برنامه‌نویس این خواهد بود که ساده‌ترین کد ممکن را بنویسد تا تست pass شود.

اگر نرم‌افزار امکانات مورد انتظار (specification) بیشتری دارد، تست‌های بیشتری باید بنویسیم و چرخه refactor و بهینه کردن کد را ادامه دهیم. وقتی همه مشخصات نرم‌افزار تست داشتند و تست‌هایشان pass می‌شد نرم‌افزار آماده است.

چرا باید از TDD استفاده کنیم؟مزایای زیادی برای استفاده از روش TDD‌ در توسعه نرم‌افزار وجود دارد.
برخی از این مزایا واضح هستند و بعضی نه. شاید واضح‌ترین مزیت این باشد که کد شما وقتی کاملاً منطبق بر نیازهای مورد انتظار نرم‌افزار نیست،‌ مشکلات و باگ‌های کمتری خواهد داشت. یکی از انواع باگ‌هایی که TDD می‌تواند به صورت کامل حذفشان کند، "باگ‌های زامبی" هستند: باگ‌هایی که به نظر می‌رسد رفع شده‌اند ولی در چند build‌ بعدتر دوباره ظاهر می‌شوند!
وقتی رسیدگی به یک باگ یا مشکل به یک TDD کار محول می‌شود، اولین کاری که انجام می‌دهد نوشتن یک تست جدید است که باگ را آشکار و تست را fail می‌کند. بعد از این کار، برنامه‌نویس روش عادی کار در TDD را دنبال می‌کند: آن‌قدر کد بنویس که تست مورد نظر pass شود و بقیه تست‌ها هم همچنان pass شده باقی بمانند.
وقتی این کار تمام شد با فرض اینکه شما شرایطی که باعث بروز مشکل شده را به درستی تست کنید، مشکل دیگر نباید در iteration های بعدی برنامه دیده شود.
مزیت دیگر استفاده از TDD بهبود کیفیت کد است. چون شما در TDD باید ساده‌ترین کد برای pass شدن تست‌ها را بنویسند: ساده‌ترین و کوتاه‌ترین کد که معمولاً کیفیت بیشتری دارد. همچنین این کدها خوانایی بیشتری دارند که باعث می‌شود نگهداری کد ساده‌تر شود.

مزیت دیگر استفاده از TDD حذف موثر کدهای مرده از برنامه شماست.
کدهای مرده یا Dead Code کدهایی هستند که در برنامه هستند اما هیچ وقت اجرا نمی‌شوند. این کد ممکن است یک متد یا کلاس باشند که هیچ وقت فراخوانی یا ارجاع داده نشدند یا بخشی از یک شرط باشند که هیچ وقت محقق نخواهد شد.
با استفاده از TDD شما فقط کدهایی را می‌نویسید که برای pass شدن تست نیاز دارید. اگر تست‌ها بر اساس نیازمندی‌های نرم‌افزار باشند، هیچ کدی از برنامه نیست که اجرا نشود و کدهایی که با روش TDD ایجاد می‌شوند همیشه مورد استفاده قرار می‌گیرند. با این حال تغییرات در نرم‌افزار به مرور زمان ممکن است باعث شوند یک متد که امروز مورد استفاده قرار می‌گیرد فردا هیچ استفاده‌ای نداشته باشد.
با مانیتور کردن کدها در TDD اگر کدی داشته باشید که در تستی مورد استفاده قرار نگرفته از دو حال خارج نیست: یا یک تست از دست شما در رفته، یا آن کد یک کد مرده (dead code) است و باید حذف شود.