توسعه آزمون‌محور - ویکی‌پدیا، دانشنامهٔ آزاد

توسعهٔ آزمون‌محور (به انگلیسی: Test-driven development) یک فرایند توسعهٔ نرم‌افزاری است که بر پایه تکرار یک سری دوره‌های خیلی کوتاه توسعه قرار دارد: ابتدا برنامه‌نویس یک مورد آزمایشی (در ابتدا دارای شکست) برای بهبود مطلوب یا ایجاد قابلیت جدید می‌نویسد، سپس کمترین مقدار تغییرات کدی را که باعث قبول شدن آزمایش می‌شود می‌نویسد، سپس کد جدید را با استانداردهای قابل قبول سازماندهی مجدد می‌کند.

TDD در یک نگاه

یک مهندس نرم‌افزار آمریکایی به نام کنت بک، که توسعه یا «بازکشف» این روش را به وی نسبت می‌دهند، در سال ۲۰۰۳ اظهار داشت که TDD طرح‌های ساده و الهام بخش اعتماد به نفس را تشویق می‌کند.

Test-driven development مربوط به مفاهیم آزمون-برای اولین بار (test-first programming concepts) برنامه‌نویسی و شدید برنامه‌نویسی (extreme programming) است که در سال ۱۹۹۹[۱] مطرح شد اما اخیراً علاقه بیشتری را نسبت به خود ایجاد کرده‌است.[۲]

برنامه نویسان همین‌طور می‌توانند این مفهوم را برای بهبود و اشکال زدایی کد میراث تهیه شده با روش‌های قدیمی تر به کار گیرند.[۳]

در این روش، نرم‌افزار به‌صورت تدریجی توسعه می‌یابد. ابتدا تست‌ها و سناریوهای آزمونی تعریف می‌شوند که بر اساس نیازمندی‌ها و اهداف مشتریان تعیین می‌شوند. سپس، با نوشتن کدی ساده که تست‌ها را برآورده کند، پروسه توسعه آغاز می‌شود. در این مرحله، کد نوشته شده تنها کافیست تا تست‌ها با موفقیت اجرا شوند و همچنین ممکن است کد اولیه به صورت موقتی باشد. سپس، با ادغام قطعات کد جدید و با تضمین عبور تست‌ها، کد قابل اجرا و نهایی تولید می‌شود. این روند تکرار می‌شود تا نرم‌افزار به صورت کامل و با تمامی ویژگی‌ها و تست‌ها توسعه یابد.

استفاده از توسعه مبتنی بر آزمون برای بهبود کیفیت و قابلیت اطمینان نرم‌افزارها و افزایش سرعت توسعه بهره‌مندی‌های قابل توجهی دارد. مطالعات و پژوهش‌های انجام شده نشان می‌دهند که استفاده از توسعه مبتنی بر آزمون منجر به کاهش خطاها، اشکالات و باگ‌های نرم‌افزار، افزایش کیفیت و عملکرد آن، کاهش هزینه‌های ناشی از خطاها و تست‌های دستی و افزایش رضایت کاربران می‌شود.[۴][۵]

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

همچنین، توسعه مبتنی بر آزمون به توسعه‌دهندگان امکان می‌دهد تا روند توسعه را بهبود دهند و تغییرات در نرم‌افزار را با اطمینان و کاهش احتمال وقوع خطاها اعمال کنند. با اجرای تست‌ها در هر مرحله از توسعه، تأیید می‌شود که تغییرات و بهبودهای اعمال شده در نرم‌افزار به عنوان انتظاری که دارند عمل می‌کنند و هیچ اثر غیرمنتظره‌ای در سایر قسمت‌های نرم‌افزار ایجاد نمی‌شود.

با توجه به مزایای مذکور و مطالعات انجام شده در زمینه توسعه مبتنی بر آزمون، این روش به عنوان یک روش مؤثر در توسعه نرم‌افزار، با توجه به شواهد علمی و مزایای آن، بسیار مورد توجه قرار گرفته‌است.

چرخه توسعه آزمون محور[ویرایش]

یک نمایش گرافیکی از چرخه حیات گرافیکی توسعه آزمون محور (test-driven development lifecycle)

چرخه توسعه آزمون محور (به انگلیسی: Test-driven development؛ به اختصار TDD) یک فرایند توسعه نرم‌افزار است که متکی بر تکرار یک چرخه توسعه بسیار کوتاه است که طی آن نیازمندی‌ها تبدیل به موارد آزمون بسیار خاص می‌شوند و سپس نرم‌افزار به قدری بهبود بخشیده می‌شود که فقط بتواند تست‌های مطرح شده را پاس کند. این روند مخالف نحوه توسعه سنتی نرم‌افزار است که اجازه می‌دهد تا بخش‌هایی به نرم‌افزار اضافه شود که هنوز تست‌های لازم را نگذرانده‌است و سپس آن بخش‌های جدید را تست می‌کند.

توسعه آزمون محور، بر مبنای نوشتن آزمون (Test) برای نرم‌افزار بر اساس نیازمندی‌ها (requirements) قبل از نوشتن برنامه شکل گرفته‌است. در این فرایند هدف توسعه دهنده معطوف به گذراندن این تست‌ها می‌شود. ابتدا چون برنامه خالی است، تمامی آزمون‌ها باید با عدم موفقیت رو به رو شوند، اما برنامه‌نویس گام به گام برای هر ویژگی (feature) این آزمون‌ها را پشت سر می‌گذارد که اگر در هر مرحله موفقیت‌آمیز نبود، بازمی‌گردد و کد را دیباگ می‌کند.

البته باید توجه داشت که در متدولوژی TDD علاوه بر آزمون‌های گام به گام نیازمند آزمون‌های موازی مستقل نیز هستیم.

چرخه کلی روش توسعه آزمون محور شامل گام‌هایی به ترتیب زیر است که بر اساس کتاب Test-Driven Development by Example نوشته شده‌است:[۶]

۱. یک تست جدید بنویس[ویرایش]

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

۲. تمام تست‌ها را اجرا کن و ببین آیا تست جدید پاس می‌شود یا خیر[ویرایش]

در این مرحله قصد داریم مطمئن شویم تست جدیدی که افزودیم خطا بدهد، وگرنه با افزودن کد جدید امکان اینکه چک شود ویژگی جدید واقعاً به درستی افزوده شده‌است یا خیر وجود نخواهد داشت.

۳. کد را بنویس[ویرایش]

فرایند پنج مرحله‌ای دقیق‌تر برای توسعه تست محور

در این گام تنها کد اضافه ای که نیاز هست تا تست جدید پاس شود را می‌نویسیم و به زیاده روی در توسعه نمی‌پردازیم.

۴. مجدداً تست‌ها را اجرا کن[ویرایش]

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

۵. کد را Refactor کن[ویرایش]

روشن است که کد کل برنامه باید هر چند وقت یک بار تمیز و مرتب شود تا از ایجاد کد کثیف اجتناب شود و امکان بهبود مناسب و سریع در آینده فراهم باشد. در این گام قصد داریم دقیقاً همین کار را انجام دهیم. در این گام به‌طور ویژه لازم است به ملاحظات توسعه همانند رعایت وراثت و خوانایی و امکان نگهداری مناسب کد و الگوهای طراحی برنامه توجه داشته باشیم.

۶. گام‌های ۱ الی ۵ را (برای هر ویژگی جدید که اضافه می‌کنی) تکرار کن[ویرایش]

برای هر ویژگی جدید گام‌های فوق را تکرار می‌کنیم.

اصول کلیدی توسعه آزمون محور[ویرایش]

TDD که در بین برنامه‌نویسان به دلیل توانایی خود در افزایش بهره‌وری، کیفیت نرم‌افزار و قابلیت نگهداری شهرت دارد، بر سه اصل اساسی بنا شده‌است. این اصول شامل مفاهیم Test-First، توسعه incremental و تست مکرر است.

روش Test-First: در TDD، تست‌ها نقشی محوری در سراسر فرایند توسعه دارند. آن‌ها به عنوان ناوبر عمل می‌کنند و کل سفر را هدایت می‌کنند. هر چرخه توسعه با ایجاد یک تست که عملکرد مورد نظر را تعریف می‌کند، آغاز می‌شود. TDD از چارچوب‌های تست خودکار استفاده می‌کند و آزمایش را در هر زمان معین تسهیل می‌کند. این امکان بازخورد دقیق و سریع در مورد رفتار برنامه را فراهم می‌کند.

توسعه incremental: با پذیرش توسعه incremental، پروژه‌ها به‌طور طبیعی به اجزای کوچک‌تر و قابل مدیریت‌تر تقسیم می‌شوند. این رویکرد تمرکز برنامه‌نویس را بر روی مشکل در دست، افزایش می‌دهد و در عین حال فرصت‌هایی را برای برنامه‌ریزی بهتر و توسعه برتر فراهم می‌کند.

تست مکرر: تست مکرر بازخورد ارزشمندی را در رابطه با نیازمندی‌های اجرا شده به برنامه‌نویسان ارائه می‌دهد. این به تشخیص زودهنگام عیوب کمک می‌کند و احتمال انتشار آن‌ها را کاهش می‌دهد. در نهایت، این مورد، منجر به افزایش سطح کیفیت و بهره‌وری می‌شود.

TDD با دریافت بازخورد سریع از طریق تست، به نوشتن کد تمیز برای پیاده‌سازی یک نیازمندی کمک می‌کند.[۷] برای توسعهٔ مبتنی بر آزمون دو قانون تعریف شده‌است:

۱- همیشه فقط در صورت شکست یک تست، برای آن کد بنویسید: این قانون بر اهمیت نوشتن یک تست شکست‌خورده قبل از پیاده‌سازی هر عملکرد جدید یا ایجاد تغییرات در کد موجود تأکید می‌کند. ایده این است که با ایجاد یک مورد آزمون (test case) شروع کنید که رفتار یا ویژگی مورد نظری که می‌خواهید پیاده‌سازی کنید را تعریف می‌کند. از آن‌جایی که شما هنوز هیچ کدی ننوشته‌اید، تست با شکست مواجه خواهد شد. این موضوع، تضمین می‌کند که شما یک هدف مشخص و دقیق برای پیاده‌سازی دارید.

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

۲- همیشه تکراری را حذف کنید: این قانون توسعه‌دهندگان را تشویق می‌کند تا هر گونه افزونگی یا تکرار را در پایگاه کد خود حذف کنند. هنگامی که متوجه الگوهای تکراری یا منطق مشابه در تست‌ها یا کد تولیدی خود می‌شوید، استخراج و انتزاع آن‌ها به اجزا یا توابع reusable، مهم است.

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

این دو قانون با هم کار می‌کنند تا فرایند توسعه را در TDD هدایت کنند. با تمرکز بر نوشتن تست‌های شکست‌خورده، ابتدا مطمئن می‌شوید که کد شما نیازمندی‌های مورد نظر را برآورده می‌کند. به‌طور هم‌زمان، با حذف تکراری‌ها، پایگاه کد خود را قابل مدیریت‌تر و قابل درک‌تر می‌کنید که منجر به توسعهٔ بهتر می‌شود.

با توجه به این دو قانون، توسعهٔ مبتنی بر آزمون را می‌توان به عنوان یک مدل توسعهٔ iterative تعریف کرد که در آن برنامه‌نویس موارد آزمون را قبل از نوشتن کد با استفاده از نیازمندی‌ها استخراج می‌کند. سپس کدی برای افزایش عملکردی کوچک نوشته می‌شود تا در تست پاس شود و در صورت شکست تست، کد می‌تواند به‌طور مکرر برای افزایش کیفیت و طراحی مجدداً تغییر داده شود.

مزایای توسعه آزمون محور[ویرایش]

یک مطالعه در سال ۲۰۰۵ به این نتیجه رسید که استفاده از روش توسعه آزمون محور به معنی نوشتن تعداد بیشتری تست هست و برنامه‌نویسانی که تعداد بیشتری تست می‌نویسند (برخلاف تصور عموم) بازدهی بیشتری دارند. همین‌طور برنامه‌نویسانی که از روش توسعه آزمون محور بهره می‌بردند گزارش کردند که به تعداد دفعات کمتری نیاز به استفاده از Debugger در کار خود داشتند، که این امر به نوبه خود موجب بهبود و افزایش بهره‌وری آنها می‌شود. چنین کاهشی در تعداد دفعات نیاز به استفاده از Debugger طبیعی به نظر می‌رسد، چرا که هر گام از توسعه و هر ویژگی جدیدی که به برنامه افزوده می‌شود خود همراه با تست در محل می‌باشد و تا زمانی که تست مربوطه و تمام تست‌های پیشین برنامه پاس نشوند به مرحله بعد نمی‌رویم. همین‌طور گزارش شده‌است که در روش توسعه آزمون محور هرگاه به خطایی برخورد کنیم معمولاً بازگشت به آخرین نسخه بدون خطا و شروع مجدد کار بهینه تر از استفاده از Debugger است که این امر عملاً نیاز به دیباگ کردن کد و هزینه‌های مالی و زمانی نگهداری و تعمیر کد را کاهش می‌دهد.

از ویژگی‌ها و مزیت‌های دیگر این متدولوژی می‌توان موارد زیر را نام برد:

۱. بررسی کامل‌تر در ابتدا[ویرایش]

این فرایند باعث می‌شود قبل از نوشتن برنامه، به جنبه‌های مختلف نیازمندی‌ها فکر کنیم و مواردی که روش‌های موجود می‌توانند شکست بخورند را بررسی کرده و در داخل آزمون‌ها در نظر بگیریم.

۲. متمرکز کردن اهداف[ویرایش]

برنامه‌نویس هدف خود را با داشتن آزمون‌ها به روشنی می‌داند و می‌توانند صرفاً با تمرکز بر روی همین آزمون‌ها، از یک هدف و نیازمندی مبهم خود را دور کند.

۳. کاهش هزینه‌ها در نهایت[ویرایش]

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

۴. توسعه گام به گام[ویرایش]

در بسیاری از موارد پیش آماده که برنامه را کامل نوشتیم و بعد به آزمون آن پرداختیم و به اشکالی برخوردیم، ولی چون از سر منشأ مشکلات به صورت دقیق آگاه نبودیم، نتوانستیم آن‌ها را رفع کنیم. توسعه آزمون محور این مسئله را نیز برای ما برطرف می‌کند.

۵. مستندسازی[ویرایش]

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

۶. کدهای مرتب‌تر[ویرایش]

با توجه به این که از رفتار تابع‌ها به صورت مجزا می‌توان اطمینان یافت، می‌توان refactoring را به صورت آنی‌تری انجام داد، همچنین سطح‌های دسترسی توابع (خصوصی و عمومی) را پس از اطمینان از صحت درستی به صورت درجا مشخص کنیم و مجبور نشویم برای تست یک تابع در توابع دیگر این سطح دسترسی‌ها را تغییر دهیم. استفاده از TDD منجر به نوشتن کدی می‌شود که تضمین می‌کند که هر بخش از کد، انجام وظایف خود را با دقت و صحت بالا انجام می‌دهد. این روش کمک شایانی می‌کند تا با اعتماد بیشتر به کدی که نوشته‌شده‌است، بتوانید آن را بهبود دهید. مخصوصاً از آن‌جا که شما در ابتدا کدی می‌نویسید که تست را پاس کند و سپس آن را refactor می‌کنید، مطمئن خواهید بود که کد شما شامل قسمت‌هایی که اضافه باشند و نیاز نشوند، نمی‌باشد و همچنین کد شما بهینه و مرتب و منطبق بر اصول clean code می‌باشد.[۸]

۷. کاهش هزینهٔ زمانی رفع مشکلات کد و دیباگ کردن آسان‌تر[ویرایش]

با استفاده از TDD از آن‌جا که از مراحل ابتدایی تست‌ها نوشته می‌شوند، خطاها در مراحل بسیار زودتری شناخته می‌شوند و در مراحل زودتری معمولاً حل می‌شوند. این کار باعث می‌شود که نیاز به صرف زمان و هزینه برای رفع خطاهای بزرگ در مراحل بعدی کاهش می‌یابد. این به معنی صرفه‌جویی در زمان و منابع می‌باشد و سرعت توسعهٔ محصول نیز در این حالات نسبت به حالت عادی که زمان زیادی را برای دیباگ کردن صرف می‌کنیم به‌طور قابل توجهی بیشتر می‌شود.[۹]

۸. Test Coverage بالا و تضمین بیشتر از نرم‌افزار[ویرایش]

با استفاده از TDD از آن‌جا که برای هر فیچری شما تست دارید، پس درصد بخشی از کد که به وسیلهٔ تست‌ها پوشش داده می‌شوند و تست می‌شوند بیشتر از سایر متودولوژی‌ها می‌باشد. همچنین از آن‌جا که برنامهٔ ما با unit testهای مختلف یا به‌طور کلی آزمون‌های مختلفی سنجیده می‌شود، می‌توانیم اطمینان خوبی از عملکرد آن داشته باشیم.[۱۰]

محدودیت‌ها و معایب توسعهٔ تست محور[ویرایش]

۱. ناتوانی در استفادهٔ عملی[ویرایش]

در شرایط پذیرش و استفاده در صنعت، موانع فنی زیادی در هنگام پیاده‌سازی وجود دارد علاوه بر این که درک کامل این که چگونه باید آن را به کار گرفت، مشکل است و برداشت‌های متفاوتی از آن میان افراد مختلف وجود دارد؛ بنابراین، استفاده عملی از آن بسیار کم است که می‌توان آن را به عنوان یکی از معایب TDD دید. طبق بررسی‌ها تنها ۱۲ درصد از TDD به روش صحیح استفاده می‌کنند. احتمالاً با دستورعمل‌هایی که نحوهٔ درست پیاده‌سازی را پیشنهاد می‌دهند و افزایش دانش صنعت، بتوان این مورد را کمی بهبود بخشید.[۱۱]

۲. سرعت توسعه[ویرایش]

TDD ممکن است باعث کاهش سرعت توسعهٔ کد شود. طراحی و نوشتن تست‌ها به تنهایی زمان‌بر است و ممکن است در ابتدا توسعهٔ کد و پیشروی را به‌طور قابل توجهی کندتر کند. علاوه بر این، این روش نیازمند تجربه و آموزش زیادی می‌باشد تا بهره‌وری بالایی از آن به‌دست آید. به همین دلیل، توسعه‌دهندگان جدید ممکن است برای استفاده از TDD نیاز به یادگیری و تسلط بیشتری داشته باشند.[۱۲]

۳. پیچیدگی بیشتر در فرایند توسعه و افزایش هزینه در برخی موارد[ویرایش]

یکی دیگر از معایب TDD، ایجاد پیچیدگی در فرایند توسعه است. این روش نیازمند توجه و هماهنگی بیشتری در نوشتن تست‌ها، پیاده‌سازی کدها و اجرای تست‌ها است. همچنین، برای توسعه‌دهندگانی که به سیستم وارد می‌شوند، ممکن است برای درک کامل فرایند نیاز به زمان و تلاش و توجه بیشتری داشته باشند. این می‌تواند باعث کاهش کارایی و افزایش هزینه توسعه شود.

مقایسهٔ توسعهٔ مبتنی بر آزمون با دیگر متدولوژی‌ها[ویرایش]

در این بخش، توسعه مبتنی بر آزمون را با روش‌های سنتی مانند توسعه مبتنی بر نیازمندی‌ها (Requirement-driven Development) و توسعه مبتنی بر مستندات (Documentation-driven Development) مقایسه می‌کنیم.

در توسعه مبتنی بر نیازمندی‌ها، نرم‌افزار بر اساس نیازمندی‌های کاربران و مشتری‌ها فنی توسعه می‌یابد. در این روش، ابتدا نیازمندی‌ها تعریف می‌شوند و سپس کد نوشته می‌شود تا نیازمندی‌ها را برآورده کند. تست‌ها و آزمون‌ها نیز پس از نوشتن کد، اجرا می‌شوند. این رویکرد ممکن است باعث ایجاد تست‌های ناکارآمد و کاهش کیفیت نرم‌افزار شود.[۱۳] در مقابل، توسعه مبتنی بر آزمون با تعریف تست‌ها در مرحله ابتدایی توسعه، از کاهش خطاها و بهبود کیفیت و قابلیت اطمینان نرم‌افزار بهره می‌برد.

در توسعه مبتنی بر مستندات، نرم‌افزار بر اساس مستندات و مشخصات فنی توسعه می‌یابد. در این روش، مستندات تهیه می‌شوند و بر اساس آن‌ها نرم‌افزار پیاده‌سازی می‌شود. تست‌ها و آزمون‌ها نیز بعد از نوشتن کد، اجرا می‌شوند. اما ممکن است در این رویکرد، تست‌ها برای بررسی جوانب‌های مختلف نرم‌افزار کافی نباشند و خطاهای مختلفی در فرایند توسعه رخ دهد.[۱۴] در مقابل، توسعه مبتنی بر آزمون با تعریف تست‌ها و سناریوهای آزمون کاملتر، تمام جوانب و قابلیت‌های نرم‌افزار را بررسی کرده و از کیفیت و عملکرد صحیح نرم‌افزار اطمینان حاصل می‌کند.

مطالعات نشان داده‌اند که استفاده از توسعه مبتنی بر آزمون منجر به کاهش خطاها، اشکالات و باگ‌های نرم‌افزار، افزایش کیفیت و عملکرد آن، کاهش هزینه‌های ناشی از خطاها و تست‌های دستی و افزایش رضایت کاربران می‌شود.[۱۵] در واقع، توسعه مبتنی بر آزمون با استفاده از رویکرد طراحی آزمون اول و پیاده‌سازی کد بر اساس آزمون‌ها، موجب تضمین عملکرد صحیح و قابل اعتماد نرم‌افزار و کاهش خطاها می‌شود.

با توجه به مزایای مذکور و مطالعات انجام شده در زمینه توسعه مبتنی بر آزمون، این روش به عنوان یک روش مؤثر در توسعه نرم‌افزار، با روش‌های سنتی مانند توسعه مبتنی بر نیازمندی‌ها و مستندات قابل مقایسه است و بهبود قابل توجهی در کیفیت و عملکرد نرم‌افزارها را به همراه دارد.

فریم‌ورک‌های توسعهٔ مبتنی بر آزمون[ویرایش]

در این بخش قصد داریم چند نمونه از فریم‌ورک‌هایی که برای توسعهٔ مبتنی بر آزمون وجود دارد را معرفی کنیم. برای زبان‌های برنامه‌نویسی مختلف که هر کدام ویژگی‌های خاص خود را دارند، فریم‌ورک‌های مختلفی وجود دارد که در این بخش به بررسی تعدادی از محبوب‌ترین آن‌ها می‌پردازیم:

csUnit: فریم‌ورک csUnit یک ابزار رایگان و متن‌باز برای تست پروژه‌های NET. است و طوری طراحی شده‌است تا برای تمام زبان‌های .NET مانند C# و C++ کار کند. از دیگر فریم‌ورک‌های محبوب توسعهٔ مبتنی بر آزمون برای زبان‌های NET. می‌توان به NUnit اشاره کرد.[۱۶]

PyUnit: یک ابزار استاندارد آزمون واحد پروژه‌های پایتون است که توسط کنت بک و اریک اما طراحی شده‌است. در پکیج‌های پایتون با نام unittest می‌توان از این ابزار استفاده کرد. PyUnit از موارد آزمون و ابزار اجرای تست (test runners) پشتیبانی می‌کند. در PyUnit شما می‌توانید موارد آزمون را طوری سازماندهی کنید که رشته‌های تعدادی از آن‌ها با ویژگی‌های یکسان اجرا شوند.

JUnit: یک ابزار آزمون واحد برای زبان برنامه‌نویسی جاوا است. JUnit بخش مهمی از توسعهٔ مبتنی بر آزمون است و از خانواده فریم‌ورک‌های آزمون واحد به اسم xUnit می‌باشد.

TestNG: یک فریم‌ورک محبوب تست برای زبان برنامه‌نویسی جاوا است که به کاربران اجازهٔ اجرای آزمون‌های خودکار برای اپلیکیشن‌های وب را می‌دهد. این فریمورک متن‌باز است و قابلیت‌های بیش‌تری نسبت به JUnit دارد که باعث افزایش محبوبیت آن در برنامه‌نویسان زبان جاوا شده‌است. هم‌چنین می‌توان با استفاده از این فریم‌ورک به همراه Selenium که یک ابزار برای مرور خودکار صفحات وب است، تست‌های خودکار قدرتمندی برای اپلیکیشن‌های وب ایجاد کرد.[۱۷]

Rspec: یک فریم‌ورک انجام آزمون برای زبان برنامه‌نویسی ruby است.

کارهای آزمون محور[ویرایش]

روش آزمون محور (به انگلیسی: Test-driven Work) در خارج از حیطه توسعه نرم‌افزار نیز به کار گرفته شده‌است. این روش تحت عنوان کار آزمون محور در تیم‌های تولیدی و خدماتی مورد استفاده قرار گرفته‌است. در کار آزمون محور همانند توسعه نرم‌افزار آزمون محور، تیم‌ها تعداد آزمون کنترل کیفیت برای هر جنبه از موضوع کار طراحی می‌کنند و سپس به ارزیابی آن و طراحی جهت ارضای آن می‌پردازند تا موفق شوند آن را پاس کنند.

شش گام ذکر شده در توسعه نرم‌افزار آزمون محور با تغییراتی جزئی به شکل زیر برای کار آزمون محور نیز به کار گرفته می‌شوند:

  1. "افزودن چک" به جای "افزودن آزمون
  2. "اجرای تمام چک‌هاً به جای "اجرای تمام آزمون‌ها
  3. "انجام کار" به جای "نوشتن کد
  4. "اجرای تمام چک‌هاً به جای "اجرای تمام آزمون‌ها
  5. "کار را مرتب کن" به جای "کد را Refactor کن
  6. «گام‌های ۱ الی ۵ را (برای هر ویژگی جدید که اضافه می‌کنی) تکرار کن» (بدون تغییر نسبت به TDD)

روش‌های برتر در توسعهٔ مبتنی بر آزمون[ویرایش]

در این قسمت تعدادی از روش‌های برتر (best practices) توسعهٔ مبتنی بر آزمون را بررسی می‌کنیم:

فهم واضح نیازمندی‌ها هنگام شروع: برای شروع، فهم دقیق و واضحی از نیازمندی‌های ویژگی‌ای که قصد توسعهٔ آن را دارید به دست آورید. این کار به شما کمک می‌کند تا تست‌های متمرکز و مرتبط بنویسید.

نوشتن تست‌های ریز: هر تست باید روی یک رفتار یا کارایی مشخص تمرکز کند. تست‌های خود را کوتاه و متمرکز و تنها مربوط به یک جنبه از کد بنویسید. این کار خوانایی و نگهداری تست‌ها را راحت‌تر می‌کند.

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

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

به‌طور مرتب بازآرایی کنید: بعد از اینکه یک تست با موفقیت پاس می‌شود، مقداری زمان برای بازآرایی و بازسازی کد و بهبود طراحی آن، بدون اینکه رفتار آن تغییر کند بگذارید. این کار به تمیز نگه داشتن و داشتن یک پروژه قابل نگهداری کمک می‌کند.

روند اجرای تست‌ها را سریع نگه دارید: اجرای تست‌های شما باید از سرعت بالایی برخوردار باشد تا بتوانید سلامت کد خود را به سرعت بررسی کنید. سرعت بالای اجرای تست‌ها اجازه می‌دهد تا سرعت توسعهٔ بیشتری داشته باشید و مشکلات را سریع‌تر متوجه شوید.

خودکارسازی تست‌ها: از فریم‌ورک‌ها و ابزارهای خودکارسازی تست‌ها استفاده کنید تا تست‌های خود را بتوانید به صورت خودکار اجرا کنید. این کار به شما اجازه می‌دهد تا تست‌های خود را بارها و بارها به راحتی اجرا کنید و آن‌ها را با جریان کاری خود ادغام کنید و مطمئن شوید که تست‌های مطمئن و قابل اطمینانی دارید.

به صورت پیوسته تست‌های خود را اجرا کنید: تست‌های خود را با محیط توسعه ادغام کنید و خطوط continuous integration یا CI بسازید تا به صورت خودکار، هر زمان که کد تغییر می‌کند، تست‌ها را اجرا کند و نتیجه را به شما اطلاع دهد. این کار به شما کمک می‌کند که در صورت فراموشی اجرای تست‌ها، در صورتی که تست‌ها پاس نمی‌شوند، کد شما وارد مرحلهٔ تحویل به مشتری نشود و تست‌ها به صورت پیوسته اجرا شوند.

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

نمونه‌های استفاده از توسعهٔ مبتنی بر آزمون در جهان واقعی[ویرایش]

در حالی که درک مفاهیم و اصول TDD بسیار مهم است، مشاهدهٔ کاربرد عملی آن در سناریوهای دنیای واقعی، بینش ارزشمندی را در مورد مزایا و اثربخشی آن ارائه می‌دهد. در این بخش، مجموعه‌ای از نمونه‌های واقعی را که در آن TDD با موفقیت به کار گرفته شده‌است، بررسی می‌کنیم و نشان می‌دهیم که چگونه این رویکرد فرایند توسعه نرم‌افزار را متحول کرده‌است.

مبدل ارز[ویرایش]

از توسعه تست محور می‌توان برای ساخت یک مبدل ارز استفاده کرد. این فرایند با نوشتن یک تست شکست‌خورده شروع می‌شود که رفتار مورد نظر مانند تبدیل دلار به یورو را تعریف می‌کند. اجرای تست در ابتدا شکست را تأیید می‌کند و اطمینان حاصل می‌کند که آزمایش به‌طور دقیق عملکرد مورد نظر را هدف قرار می‌دهد. در مرحلهٔ بعد، حداقل کد برای گذراندن آزمون پیاده‌سازی می‌شود و پس از آن مجدداً آزمون برای اطمینان از موفقیت آن اجرا می‌شود. بازآرایی مداوم امکان بهبود کد را بدون تغییر رفتار فراهم می‌کند. افزودن مکرر موارد آزمایشی بیش‌تر، اعتبارسنجی کامل عملکرد تبدیل ارز را ممکن می‌سازد و در نتیجه یک سیستم قابل اعتماد و دقیق ایجاد می‌کند.[۱۸]

بازی بولینگ[ویرایش]

استفاده از TDD برای ایجاد یک سیستم امتیازدهی برای یک بازی بولینگ، اطمینان و دقت را تضمین می‌کند. توسعه‌دهندگان با شروع از تست‌های شکست‌خورده، منطق مورد نیاز برای گذراندن تست‌ها را به صورت تدریجی پیاده‌سازی می‌کنند. ماهیت تکرارشوندهٔ TDD امکان بازخورد و بهبود مستمر را فراهم کرده و مکانیزم امتیازدهی قوی را تضمین می‌کند. اصلاح مجدد کد باعث حفظ وضوح و سادگی و رعایت اصول کد تمیز می‌شود. با پیروی از این رویکرد، توسعه‌دهندگان می‌توانند با اطمینان سیستم امتیازدهی بازی بولینگ را بسازند و اصلاح کنند.[۱۸]

اعتبار سنجی ایمیل[ویرایش]

در پروژهٔ توسعهٔ نرم‌افزار مایکروسافت، TDD می‌تواند برای پیاده‌سازی یک مؤلفهٔ اعتبارسنجی ایمیل قوی اعمال شود. فرایند TDD با نوشتن یک تست شکست‌خورده شروع می‌شود که رفتار تابع اعتبارسنجی ایمیل را تأیید می‌کند. آزمون اولیه می‌تواند قالب‌های ایمیل معتبر را بررسی کند و قالب‌های نامعتبر را رد کند. با نوشتن حداقل کد مورد نیاز برای قبولی در آزمون، توسعه‌دهندگان می‌توانند منطق اعتبارسنجی ایمیل را با استفاده از فناوری‌های Microsoft.NET پیاده‌سازی کنند. اجرای تست تضمین می‌کند که کد به درستی عمل می‌کند. تکرارهای بیشتر شامل اضافه کردن تست‌های بیش‌تر، مانند بررسی موارد لبه و مدیریت فرمت‌های مختلف ایمیل است. TDD تضمین می‌کند که مؤلفهٔ تأیید اعتبار ایمیل قابل اعتماد، دقیق است و می‌تواند سناریوهای مختلفی را در اکوسیستم Microsoft.NET مدیریت کند.[۱۹]

احراز هویت کاربر[ویرایش]

در یک محیط توسعهٔ Microsoft.NET، توسعهٔ مبتنی بر آزمون می‌تواند برای توسعهٔ یک ماژول احراز هویت کاربر برای یک برنامه استفاده شود. این فرایند با نوشتن تست‌هایی آغاز می‌گردد که قابلیت‌های ورود و ثبت نام کاربر را با استفاده از فناوری‌ها و چارچوب‌های مایکروسافت تأیید می‌کند. تست‌های ناموفق تضمین می‌کنند که رفتار مورد نظر به درستی هدف قرار گرفته‌است. سپس حداقل کد مورد نیاز برای قبولی در آزمون‌ها با استفاده از ابزار Microsoft.NET پیاده‌سازی می‌شود. با اجرای تست‌ها، توسعه‌دهندگان می‌توانند منطق ورود و ثبت نام در اکوسیستم مایکروسافت را تأیید کنند. گسترش مکرر مجموعهٔ آزمایشی سناریوهایی مانند قدرت رمز عبور، بازیابی حساب و کنترل دسترسی مبتنی بر نقش را پوشش می‌دهد و از قابلیت‌های Microsoft.NET بهره می‌برد. TDD یک سیستم احراز هویت کاربر ایمن و قابل اعتماد را با اعتبارسنجی کامل کد پیاده‌سازی شده در برابر موارد آزمایشی با استفاده از فناوری‌های مایکروسافت تضمین می‌کند.[۱۹]

آیندهٔ توسعهٔ مبتنی بر آزمون[ویرایش]

آیندهٔ توسعهٔ مبتنی بر آزمون چشم‌اندازهای امیدوارکننده‌ای دارد زیرا شیوه‌های توسعهٔ نرم‌افزار همچنان در حال تکامل هستند. مطالعه‌ای که در[۲۰] انجام شده مزایای TDD را در محیط‌های صنعتی در دنیای واقعی به نمایش گذاشته‌است. این تحقیق نشان می‌دهد که TDD نه تنها کیفیت کد را بهبود می‌بخشد، بلکه چگالی خطا یا defect را کاهش می‌دهد و بهره‌وری توسعه‌دهندگان را افزایش می‌دهد. این یافته‌ها پتانسیل TDD را برای شکل‌دادن به آیندهٔ توسعهٔ نرم‌افزار با توانمند ساختن تیم‌ها برای ساختن نرم‌افزارهایی با کیفیت بالاتر و کارآمدتر نشان می‌دهد.

همان‌طور که سیستم‌های نرم‌افزاری پیچیده‌تر می‌شوند، اهمیت تضمین قابلیت اطمینان و امنیت آن‌ها بالاتر می‌رود. کتاب[۲۱] به ساختن نرم‌افزارهای قوی و انعطاف‌پذیر تأکید می‌کند. با نوشتن تست‌ها قبل از پیاده‌سازی کد، توسعه‌دهندگان می‌توانند نقص‌ها و آسیب‌پذیری‌های طراحی را در مراحل اولیهٔ توسعه کشف کنند و احتمال ایجاد نقص‌های مهم را کاهش دهند. این رویکرد پیشگیرانه برای تست کردن با اصول تست Shift-left و DevSecOps همسو می‌شود؛ جایی که امنیت و آزمایش از همان ابتدا در چرخهٔ عمر توسعهٔ نرم‌افزار یکپارچه شده‌است. از آن‌جایی که صنعت نرم‌افزار همچنان امنیت و قابلیت اطمینان را در اولویت قرار می‌دهد، TDD آماده است تا نقش مهمی در تقویت نرم‌افزار در برابر تهدیدات احتمالی ایفا کند.

ظهور معماری میکروسرویس‌ها و محاسبات ابری، شیوهٔ ساخت و استقرار سیستم‌های نرم‌افزاری را متحول کرده‌است. ماهیت تکرارشونده و مبتنی بر بازخورد TDD با چابکی و مقیاس‌پذیری میکروسرویس‌ها هماهنگ است. با نوشتن تست‌ها در ابتدا و طراحی APIها بر اساس نیازهای مشتری، توسعه‌دهندگان می‌توانند اطمینان حاصل کنند که میکروسرویس‌ها به درستی کار می‌کنند و به‌طور یکپارچه در یک سیستم بزرگتر ترکیب می‌شوند. از آنجایی که سازمان‌ها به پذیرفتن میکروسرویس‌ها و معماری‌های بومی ابری ادامه می‌دهند، TDD پایهٔ محکمی برای ساخت سرویس‌های ماژولار که می‌توانند به‌طور مستقل آزمایش و اجرا شوند، فراهم می‌کند.

جستارهای وابسته[ویرایش]

منابع[ویرایش]

  1. Lee Copeland (December 2001). "Extreme Programming". Computerworld. Retrieved January 11, 2011.
  2. Newkirk, JW and Vorontsov, AA. Test-Driven Development in Microsoft .NET, Microsoft Press, 2004.
  3. Feathers, M. Working Effectively with Legacy Code, Prentice Hall, 2004
  4. George, Boby; Williams, Laurie (2003-03-09). "An initial investigation of test driven development in industry". Proceedings of the 2003 ACM symposium on Applied computing. New York, NY, USA: ACM. doi:10.1145/952532.952753.
  5. Romano, Simone; Zampetti, Fiorella; Baldassarre, Maria Teresa; Di Penta, Massimiliano; Scanniello, Giuseppe (2022-09-19). "Do Static Analysis Tools Affect Software Quality when Using Test-driven Development?". ACM / IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM). New York, NY, USA: ACM. doi:10.1145/3544902.3546233.
  6. Beck, K. Test-Driven Development by Example, Addison Wesley - Vaseem, 2003
  7. Kanwal, Faria; Junaid, Komal; Fahiem, Muhammad Abuzar (2010). "A Hybrid Software Architecture Evaluation Method for FDD - An Agile Process Model". 2010 International Conference on Computational Intelligence and Software Engineering. IEEE. doi:10.1109/cise.2010.5676863.
  8. «Advantages and disadvantages of Test Driven Development (TDD)». GeeksforGeeks (به انگلیسی). ۲۰۲۰-۱۲-۱۴. دریافت‌شده در ۲۰۲۳-۰۷-۰۴.
  9. Khanam, Zeba; Ahsan, Mohammed Najeeb (2018). "Implementation of the pHash algorithm for face recognition in a secured remote online examination system". International Journal of Advances in Scientific Research and Engineering. 4 (11): 01–05. doi:10.31695/ijasre.2018.32917. ISSN 2454-8006.
  10. "The Benefits of Test-Driven Development (TDD) | Northcoders". northcoders.com (به انگلیسی). Retrieved 2023-07-04.
  11. Kristav, Per; Bäckström, Izabelle; Nordin, Axel; Warell, Anders; Diegel, Olaf (2018-12-31). "A Multi-Dimensional Framework for the Development of Authentic Consumer Products". Journal of Marketing and Consumer Behaviour in Emerging Markets. 2/2018 (8): 46–65. doi:10.7172/2449-6634.jmcbem.2018.2.4. ISSN 2449-6634.
  12. Beginners, Benefits Of Test-Driven Development – A. Guide For. "Benefits Of Test-Driven Development – A Guide For Beginners". Benefits Of Test-Driven Development – A Guide For Beginners (به انگلیسی). Retrieved 2023-07-04.
  13. Romano, Simone; Zampetti, Fiorella; Baldassarre, Maria Teresa; Di Penta, Massimiliano; Scanniello, Giuseppe (2022-09-19). "Do Static Analysis Tools Affect Software Quality when Using Test-driven Development?". ACM / IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM). New York, NY, USA: ACM. doi:10.1145/3544902.3546233.
  14. George, Boby; Williams, Laurie (2003-03-09). "An initial investigation of test driven development in industry". Proceedings of the 2003 ACM symposium on Applied computing. New York, NY, USA: ACM. doi:10.1145/952532.952753.
  15. Romano, Simone; Zampetti, Fiorella; Baldassarre, Maria Teresa; Di Penta, Massimiliano; Scanniello, Giuseppe (2022-09-19). "Do Static Analysis Tools Affect Software Quality when Using Test-driven Development?". ACM / IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM). New York, NY, USA: ACM. doi:10.1145/3544902.3546233.
  16. "NUnit". Wikipedia (به انگلیسی). 2022-11-02.
  17. «How to Automate TestNG in Selenium ?». BrowserStack (به انگلیسی). بایگانی‌شده از اصلی در ۲ ژوئیه ۲۰۲۲. دریافت‌شده در ۲۰۲۳-۰۷-۰۶.
  18. ۱۸٫۰ ۱۸٫۱ Ashbacher, Charles (2003). "Test-Driven Development: By Example, by Kent Beck". The Journal of Object Technology. 2 (2): 203. doi:10.5381/jot.2003.2.2.r1. ISSN 1660-1769.
  19. ۱۹٫۰ ۱۹٫۱ Easton, M. J.; King, Jason (2004). "Cross-Platform .NET Development: Using Mono, Portable.NET, and Microsoft .NET". doi:10.1007/978-1-4302-0746-7. {{cite journal}}: Cite journal requires |journal= (help)
  20. Nagappan, Nachiappan; Maximilien, E. Michael; Bhat, Thirumalesh; Williams, Laurie (2008-02-27). "Realizing quality improvement through test driven development: results and experiences of four industrial teams". Empirical Software Engineering. 13 (3): 289–302. doi:10.1007/s10664-008-9062-z. ISSN 1382-3256.
  21. Balland, Emilie; Moreau, Pierre-Etienne; Reilles, Antoine (2012-10-04). "Effective strategic programming for Java developers". Software: Practice and Experience. 44 (2): 129–162. doi:10.1002/spe.2159. ISSN 0038-0644.

پیوند به بیرون[ویرایش]