صفحه ی لینکدین من: https://www.linkedin.com/in/mohaddese-salem-27388318b
تستها، مسئول محافظت از اجرای نیازمندیهای اصلی نرمافزار
در بخش قبلی این سری مقاله، دربارهی اهمیت و ضرورت تست نرمافزار صحبت کردیم و متوجه شدیم که اگر قبل از انتشار نرمافزار و رسیدن آن به دست کاربر، ایرادات موجود در پروژه را متوجه نشویم؛ به احتمال زیاد، کاربر در حین کارکردن با نرمافزار ما، به مشکل پی میبرد و آن زمان است که دیگر آب رفته به جوی بازگردانده نمیشود و بسته به اینکه مشکل پیش آمده برای او، تا چه حد مهم و بزرگ باشد؛ میتواند باعث بیاعتمادی کاربر به محصول نرمافزاری ما و احیانا تبلیغات منفی علیه آن شود و این اتفاق، در طولانی مدت خسارات کوچک و بزرگ اقتصادی و اجتماعی زیادی را برای شرکت به همراه دارد. پس بهتر است قبل از اینکه برای درمان این خسارات هزینه کنیم، بودجهای را برای پیشگیری کنار بگذاریم چراکه به هرحال، بهمراتب بهتر از درمان است.
قبل از اینکه کدهای برنامه توسعه داده شود، به فکر تستکردن آن باشید!
یکی از رویکرد های خیلیخوبی که در توسعهی یک نرمافزار وجود دارد، این است که قبل از توسعهی یک برنامه، unit test case های مربوط به آن را طراحی کنیم. یعنی در هنگام طراحی معماریها و طرحهای اولیهی نرمافزار، برای هر بخش مشخص کنیم که: (اگر این بخش از برنامه به چه نتیجه ای برسد، ما خواهیم گفت که کار خود را به خوبی انجام داده است؟!) این کار باعث میشود که هم در حین طراحی معماری نرمافزار و هم در هنگام توسعه ی کدها، ذهنیت بهتری درباره ی هربخش داشته باشیم و بدانیم بخش موردنظر را چطور توسعه بدهیم تا انتظاراتی که طراحان برنامه از آن دارند (و درون تست ها، به روشنی آن را توصیف کرده اند) برآورده شود.
به همین دلیل، قبل از اینکه دربارهی انواع مختلف تست صحبت کنیم، ابتدا مراحل تولید و طراحی یک نرمافزار را بهطور کلی مرور میکنیم تا بتوانیم دید بهتری درباره ی انواع مختلف تستهای مورد نیاز داشته باشیم.
مراحل طراحی یک محصول نرمافزاری
داستان طراحی یک نرمافزار، از اینجا شروع میشود که ابتدا صاحبان یا ذینفعان نرمافزار موردنظر، با مدیر فنی تیمی که میخواهند مسئولیت توسعهی نرمافزار را به آنان بسپرند، یک جلسه میگذارند و در آن، تمام ویژگیهایی که میخواهند محصول نهایی داشته باشد را به همراه ملاحظاتی که از نظر بودجه، سیاستهای شرکت یا سازمان موردنظر و یا موراد مشابه دارند را برای او شرح میدهند. مدیرفنی تیم توسعهی نرمافزار موظف است خواستههای آنان را بشنود و باتوجه به این خواستهها، الزامات عملکردی نرمافزار را به همراه تکنولوژیهایی که میتواند به بهترین شکل خواستههای کارفرما را برآورده کند، انتخاب کند.
در مرحلهبعد، اعضای تیم مدیریت پروژه وظیفه دارند خواستههای کارفرما (که لزوما خواستههای تکنیکیای نیستند) را به صورت نیازمندیهای سیستم و به نحوی که روشن و قابل پیادهسازی باشد،در قالب نیازمندیهای سیستم بیان کنند.
تا این مرحله، قاعدتا اطلاعات کلی نرمافزار استخراج شده است و حال نوبت آن است که بیشتر وارد جزئیات فنی شویم. برای این کار، ابتدا باید معماری بخشهای مختلف برنامه توسط معمار نرمافزار ایجاد شده و سپس اسناد طراحی شده برای پیادهسازی نهایی به دست برنامهنویسها سپرده شود تا مراحل تولید برنامه آغاز شود.
در شکل بالا که بهخوبی میتواند ارتباط بین مراحل تولید و تست نرمافزار را نشان دهد؛ مطابق توضیحات بخش قبل، دیده میشود که برای تولید یک نرمافزار از بیرونی ترین حلقه به سمت درونیترین حلقه میرویم و مراحل را یک به یک پیاده سازی میکنیم. اما هنگامیکه نوبت به تست نرمافزار برسد، دقیقا برعکس جریان پیش میرویم و مراحل تست را از درونیترین حلقه به بیرونیترین حلقه طی میکنیم تا فرآیند تست از همه ی جوانب کامل شود.
مرحله اول) تست اجزاء برنامه یا Unit Test
ابتدایی ترین مرحلهی تست، Unit Test است که مطابق با مرحلهی پیادهسازی کدها در مارپیچ شکل 1 میباشد. همانطور که از این بخش مشخص است؛ در Unit Test، تمرکز ما بر این است که مطمئن شویم تکتک اجزای مستقل کد، اولا درست و منطقی کار میکنند و دوما کاری را که انتظار داریم انجام دهند را بهخوبی و کامل انجام میدهند.
البته باید بگوییم که در این تست، منظورمان از یک Unit دقیقا یک متغیر، یک متد و یا حتی لزوما یک کلاس نیست! بلکه در هر بخش و با توجه به ساختار برنامه میتواند تعبیر ما از یک Unit متفاوت باشد. برای مثال ممکن است گاهی تنها یک متد را به عنوان یک یونیت تست کنیم و گاهی نیاز است چند کلاسِ به هم مرتبط را یک واحد در نظر بگیریم و آنها را مورد آزمایش قرار دهیم.
مرحله دوم) تست یکپارچگی یا Integration Test
پس از آنکه مطمئن شدیم تکتک بخش های برنامه درست و خوب کار میکند، حال نوبت آن است که این بخش های مختلف را کنار هم قرار دهیم تا متوجه شویم که آیا این بخشها میتوانند در کنار یکدیگر نیز به خوبی کار کنند و نتیجهای که انتظار داریم از همکاری آنها حاصل شود را تولید کنند یا خیر؟! همانطور که از شکل 1 مشخص است، این مرحله از تست متناظر با طراحی معماری نرمافزار است و قاعدتا در این مرحله انتظار داریم تستهای طراحی شده مشخص کنند که آیا معماری ای که برای نرمافزار طراحی کرده ایم، بهخوبی و درست پیاده سازی شده است یا خیر؟ همچنین اگر در ارتباط بین بخش های مختلف برنامه، مشکلی وجود داشته باشد؛ در این مرحله از تست متوجه میشویم و آن را رفع میکنیم.
مرحله سوم) تست اعتبار سنجی یا Validation Test
زمانی که به این مرحله از تست وارد میشویم، تقریبا مطمئن هستیم که نرمافزار تولید شده، از نظر فنی و منطقی کاملا خوب و درست کار میکند. در این مرحله نوبت این است که متوجه شویم که آیا این محصول نرمافزاری تولید شده، دقیقا همان چیزی است که کارفرما یا ذینفعان سیستم انتظار داشته اند یا خیر؟! همانطور که از مارپیچ شکل 1 مشخص است، در این مرحله ویژگیهای محصول نهایی را با نیازمندیهایی که در ابتدا برای سیستم در نظر گرفته شده اند تطبیق میدهیم تا مطمئن باشیم که تمام ویژگی های رفتاری و عملکردی مورد نظر، در نرمافزار پیاده شده باشد و قابلیتی وجود نداشته باشد که نادیده گرفته شده و یا به اشتباه پیاده سازی شده باشد.
مرحله چهارم) تست کل سیستم یا System Test
در مرحله ی آخر فرآیند تست نرمافزار، کار انجام تست از مبحث مهندسی نرمافزار فراتر می رود و وارد مهندسی کامپیوتر می شود. در مرحلهی System Testing ، سیستمی که تقریبا مطمئنیم به تنهایی درست و خوب کار میکند، با سیستمهای دیگری که در دنیای واقعی باید در کنار آنها خوب کار کند، ترکیب می شود تا سنجیده شود که آیا این واحدهای مستقل، می توانند درکنار یکدیگر نیز خوب و بدون مشکل کار کنند یا خیر؟! برای مثال اگر نرمافزار ما نیاز داشته باشد برای انجام کارهای خود، از دیتابیسها یا سرورهایخارجی دیگری استفاده کند و یا با سامانههای دیگری تعامل کند، باید قبل از انتشار آن مطمئن شویم که در واقعیت نیز میتواند این کار را بهخوبی انجام دهد و این وظیفهی تست سیستم میباشد. برای انجام تست سیستم، قاعدتا به افراد باتجربهای نیاز داریم که دید نسبتا خوبی نسبت به بخشهای مختلف سیستم موردنظر داشته باشند تا بتوانند از درستبودن عملکرد آنها مطمئن شوند.
Source : Roger S. Pressman, Bruce R. Maxim. "Software Engineering A Practtitioner's Approach" - 9th Edition
در مقاله ی بعدی، بیشتر روی Unit Test تمرکز میکنیم و دربارهی جزئیات آن، بیشتر صحبت میکنیم. توصیه میکنم اگر این بحث، تا اینجا برایتان جذاب بوده، با من همراه باشید.
مطلبی دیگر از این انتشارات
Semantic Versioning
مطلبی دیگر از این انتشارات
pre-mature optimization is root of all evil
مطلبی دیگر از این انتشارات
تقدس گرایی؛ عامل بدبختی برنامه نویسان!