شیء ساختگی
در برنامهنویسی شی گرا، اشیاء ساختگی اشیایی شبیهسازی شدهاند که رفتار اشیاء واقعی را به صورتهای کنترل شدهای تقلید میکنند. یک برنامهنویس بهطور معمول شیء ساختگی را برای تست رفتار برخی دیگر اشیاء ایجاد میکند، همانطور که یک طراح ماشین از آدمک آزمایش تصادف استفاده میکند تا رفتار پویای انسانی را در تصادفات وسایل نقلیه شبیهسازیکند.
دلایل استفاده
در یک آزمایش واحد، اشیاء ساختگی میتوانند رفتار اشیاء پیچیده و واقعی را شبیهسازی کنند و بنابراین زمانی که ادغام کردن شیء اصلی با آزمایش واحد غیر کاربردی یا غیرممکن است مفید هستند. اگر یک شیء دارای هر کدام از ویژگیهای زیر باشد، استفاده از شیء ساختگی به جای آن میتواند مفید باشد:
- جسم نتایجی غیر قطعی فراهم میکند (به عنوان مثال زمان کنونی یا دمای کنونی)؛
- جسم حالتهایی دارد که ساختن یا بازسازی آنها دشوار است (به عنوان مثال خطای شبکه)
- جسم کند است (به عنوان مثال یک پایگاه داده کامل، که باید قبل از تست شدن مقداردهی شود)؛
- جسم هنوز وجود ندارد یا ممکن است تغییر رفتار بدهد؛
- جسم باید تنها برای تست شدن (و نه برای کار واقعی) دارای اطلاعات یا روشهایی باشد.
به عنوان مثال، یک برنامه ساعت زنگدار که در یک زمان معینی زنگ میزند، ممکن است زمان فعلی را از یک سرویس زمانی بگیرد. برای آزمایش، این ساعت باید تا زمانی مقرر صبر کند تا بتواند تشخیص دهد که زنگ در زمان صحیح به صدا درآمده است یا نه. اگر به جای سرویس زمانی واقعی از سرویس زمانی ساختگی استفاده شود، این سرویس زمانی ساختگی میتواند طوری برنامهریزی شود که زمان کوک شدهٔ ساعت (یا هر زمان دیگری) را مستقل از زمان واقعی فراهم سازد، در نتیجه برنامهٔ ساعت زنگدار میتواند در انزوا تست شود.
جزئیات فنی
اشیاء واقعی و اشیای ساختگی ای که رفتار آنها را تقلید میکنند رابط (رایانش) یکسانی و مشابهی دارند که باعث میشود کاربر متوجه نشود که از شیء واقعی استفاده میکند یا شیء ساختگی. بسیاری از چارچوبهای موجود شیء ساختگی به برنامهنویس اجازه میدهد که مشخص کند که کدام اسلوبها و به چه ترتیبی روی شیء ساختگی انجام شود و همچنین پارامترهای ورودی آنها چه باشد و چه مقدارهایی را بازگرداند؛ بنابراین رفتار یک شیء پیچیده مانند یک سوکت شبکه میتواند با شیء ساختگی تقلید شود. این موضوع به برنامهنویس اجازه میدهد که بفهمد شیء مورد نظر در حالتهای متفاوت پاسخ درستی میدهد یا نه.
ساختگیها، تقلبیها و خرافهها
طبقهبندی بین خراشها، تقلبیها و خرافهها در ادبیات بسیار متناقض است. با این وجود، شباهت بین آنها این است که همگی نشان دهندهٔ تولید یک شیء برای تست کردن برنامه با رابط (رایانش)های یکسان با شیء واقعی است.
در مورد اینکه بین ساختگی، جعلی، یا خرافه کدام یک سادهترین است، تناقضاتی وجود دارد اما سادهترین آنها همواره پاسخهای از پیش مشخص شدهای را بازمیگرداند. از طرفی، پیچیدهترین شیء خروجی را با تمام منطق و استثنائات و … شبیهسازی میکند. این که آیا هیچکدام از ساختگی، جعلی یا خرافه، متناسب با چنین تعریفی است، مجدداً متناقض است.
برای مثال پیادهسازی یک اسلوب ساختگی، تقلبی یا خرافه بین دو سر طیف پیچیدگی ممکن است شامل اعلامیههایی برای بررسی هر فراخوانی باشد. برای مثال، یک شیء ساختگی ممکن است ترتیب فراخوانی اسلوبها یا ثبات دادهها را در بین فراخوانی اسلوبها را اعلام کند.
در کتاب The Art of Testing Unit شیء ساختگی به عنوان یک شیء جعلی توصیف شدهاست که با تأیید اینکه تعامل با شیء رخ دادهاست یا نه در مورد درست یا غلط بودن تنیجهٔ تست تصمیمگیری میکند. هر چیز به عنوان شیء خرافه تعریف شدهاست. در این کتاب، هر شیء ای که واقعی نیست شیء تقلبی است، که براساس کاربرد آنها، میتواند یا ساختگی یا خرافات باشد.
تنظیم کردن انتظارات
برای مثال فرض کنید یک سیستم مجوزدهی با یک شیء ساختگی شبیهسازی شدهاست. شیء ساختگی یک اسلوب به شکل زیر را پیادهسازی میکند که با اسلوب کلاس واقعی مجوزدهی مطابقت داشته باشد:
isUserAllowed(task : Task) : boolean
اگر این اسلوب ساختگی یک ورودی دیگر به شکل isAllowed : boolean
داشته باشد بسیار مفید است زیرا در هنگام تست کد میتوانیم مشخص کنیم که یک کاربر مجوز دارد یا نه و در نتیجه با توجه به داشتن یا نداشتن مجوز رفتار باقی سیستم را در هر کدام از حالات آزمایش و تست کنیم.
به همین ترتیب، تنظیماتی که تنها در هنگام تست کردن اضافه میکنیم میتواند این امکان را به ما بدهد که قسمت شبیهسازی شده باعث ایجاد استثنا شود یا بدون اینکه خروجی بازگرداند در تابع گیر کند یا به عنوان خروجی null
برگرداند و غیره. در نتیجه این امکان وجود دارد که رفتارهای مدل سرویسگیرنده-سرویسدهنده در شرایط خطا شبیهسازی کنیم و پاسخی که سیستم در این شرایط میدهد را آزمایش کنیم. بدون داشتن چنین سیستم ساختگی ساده و قابل انعطافی تست و آزمایش کردن هر کدام از این شرایط ممکن است بسیار دشوار باشد.
نوشتن رشتههای لاگ
اسلوب ذخیرهٔ یک شیء پایگاه داده ساختگی save(person : Person)
ممکن است دارای میزان زیادی پیادهسازی نباشد و حتی ممکن است هیچ پیادهسازی نداشته باشد. ممکن است وجود و شاید معتبر بودن شیء Person که به عنوان ورودی به آن داده شدهاست تا ذخیره شود را چک نکند (به بررسی بالا در خصوص ساختگی و جعلی توجه کنید). حتی ممکن است در کل هیچ پیادهسازی نداشته باشد.
این یک فرصت از دست رفتهاست. اسلوب ساختگی میتواند یک رشته به رشتهٔ لاگهای عمومی اضافه کند. رشتهٔ لاگ شده باید بیش از «شخص ذخیره شد» باشد، یا ممکن است شامل برخی از جزئیات از نمونه شیء فرد(Person)، مانند نام یا شناسه باشد. اگر کد تست شده بعد از اجرای تعداد معینی دستور که شامل ذخیرهٔ اطلاعات شخص میشود محتویات رشتهٔ لاگها را چک کند میتواند بفهمد که اسلوب ذخیرهٔ اطلاعات شخص به تعداد بار درستی صدا شدهاست یا نه. با این روش میتوان اشکالات غیرقابل مشاهده ای که باعث ضعیف شدن عملکرد برنامه میشوند را نیز پیدا کرد. برای مثال برنامهنویس، نگران از دست دادن اطلاعات شخص، ممکن است چند بار اسلوب مورد نظر را صدا زده باشد در حالی که یک بار صدا زدن اسلوب کافی بودهاست.
استفاده در توسعه تست محور
برنامه نویسانی که با روش توسعه مبتنی بر تست (TDD) در هنگام توسعهٔ نرمافزار از اشیاء ساختگی استفاده میکنند. اشیاء ساختگی با نیازهای رابط کاربری اشیا واقعاً پیچیده مطابق هستند و جانشین آنها میشوند. در نتیجه آنها به برنامه نویسان اجازهٔ توسعهٔ قابلیتها و انجام تست واحد روی آنها را میدهند بدون این که نیاز باشد کلاسهای پیچیدهٔ اصلی و زیربنایی را صدا زنند. استفاده از اشیاء ساختگی، به توسعه دهندگان این اجازه را میدهد که تستهای خود را بر روی رفتار سیستم تحت آزمایش متمرکز کنند بدون اینکه نگران وابستگیهای آن باشند. به عنوان مثال، آزمایش یک الگوریتم پیچیده بر اساس حالتهای خاص اشیاء متعدد میتواند با استفاده از اشیاء ساختگی به جای اشیاء واقعی انجام شود.
به غیر از مسائل پیچیدگی و منافع حاصل از این تفکیک دغدغهها، مسائلی در مورد سرعت عمل نیز وجود دارد. توسعه یک تکه واقعی نرمافزار با استفاده از TDD ممکن است به راحتی شامل چندصد آزمون واحد باشد. اگر بسیاری از این آزمونها سیستم را وادار به برقراری ارتباط با پایگاه داده، سرویسهای وب و دیگر سیستمهای ارتباطات بین پردازشی یا سیستمهای شبکه کنند، آنگاه این مجموعهٔ آزمایشهای واحد سریعاً کند میشود و نمیتواند با سرعت عادی اجرا شود. این به نوبه خود منجر به عادتهای بد و بی میلی توسعه دهنده به حفظ اصول اساسی TDD میشود.
هنگامی که اشیاء ساختگی با اشیاء واقعی جایگزین میشوند، قابلیت پایان به پایان نیاز به آزمایشهای بیشتری نیاز دارد. این آزمایشها به جای آزمایشهای واحد، آزمایشهای ادغامی خواهند بود.
محدودیتها
استفاده از اشیاء ساختگی میتواند به راحتی تست واحد را به پیادهسازی کد مورد آزمایش متصل کند. به عنوان مثال، بسیاری از چارچوبهای شیء ساختگی به توسعه دهنده این اجازه را میدهند تا ترتیب و تعداد دفعات صدا شدن شیء ساختگی توسط شیء مورد آزمایش را زیر نظر بگیرد. بازسازیهای بعدی کد مورد آزمایش قرار گرفته، میتواند باعث عدم موفقیت آزمایش شود، هرچند که تمام اسلوبهای شیء ساختگی هنوز از قرارداد پیادهسازی قبلی پیروی میکنند. این نشان میدهد که تست واحد باید رفتار بیرونی اسلوب را آزمایش کند و نه پیادهسازی داخلی آن. استفاده بیش از حد از اشیاء ساختگی به عنوان بخشی از مجموعهٔ آزمونهای واحد میتواند باعث افزایش قابل توجه نیاز به نگهداری هنگام تکمیل شدن یا بازسازی سیستم شود. نگهداری نادرست چنین آزمایشهایی در طول تکامل سیستم میتواند باعث ندیدن مشکلاتی شود که در صورت استفاده از نمونه کلاسهای واقعی در تست واحد به راحتی تشخیص داده میشدند. از طرفی، استفاده از یک اسلوب ساختگی ممکن است به پیکربندی بسیار کمتر و سادهتری نسبت به راه اندازی کل کلاس واقعی نیاز داشته باشد و در نتیجه نیاز به نگهداری را کاهش دهد.
اشیاء ساختگی باید به درستی رفتار جسم واقعی را مدلسازی کنند. در صورتی که جسم واقعی توسط یک توسعه دهندهٔ دیگر نوشته شده باشد یا هنوز نوشته نشده باشد، مدلسازی درست رفتار آن میتواند دشوار باشد. اگر رفتار به درستی مدل نشده باشد، آنگاه آزمایشهای واحد ممکن است موفقیتآمیز باشد حتی اگر در زمان اجرا و در شرایطی مشابه با شرایط آزمون واحد، شکست رخ دهد؛ بنابراین نتیجهٔ تست واحد نادرست است.
جستارهای وابسته
منابع
- ↑ "Stubs and Mocks".
- ↑ "behind the times: Mocks and Stubs aren't Spies".
- ↑ "Mocks, Fakes, Stubs and Dummies at XUnitPatterns.com".
- ↑ "What's the difference between a mock & stub?".
- ↑ "What's the difference between faking, mocking, and stubbing?".
- ↑ Feathers, Michael (2005). "Sensing and separation". Working effectively with legacy code. NJ: Prentice Hall. p. 23 et seq. ISBN 0-13-117705-2.
- ↑ Osherove, Roy (2009). "Interaction testing with mock objects et seq". The art of unit testing. Manning. ISBN 978-1-933988-27-6.
- ↑ این مثالها از nomenclature استفاده میکنند که شبیه به آن در زبان مدلسازی متحد است
- ↑ Beck, Kent (2003). Test-Driven Development By Example. Boston: Addison Wesley. ISBN 0-321-14653-0.
- ↑ InJava.com به Mocking | رسانه O'Reilly