تعریف: واحد کار

ساخت وبلاگ

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

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

اعلامیه و امضای عملکرد نقطه ورود به بدن است.

خروجی ها یا رفتارهای حاصل از عملکرد نقاط خروج آن است.

نقاط ورود و نقاط خروج

یک واحد کار همیشه دارای یک نقطه ورود و یک یا چند نقطه خروج است.

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

unit-of-work1.png

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

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

unit-of-work2.png

چرا "نقطه خروج"؟

چرا "خروج از نقطه" و نه چیزی شبیه به "رفتار"؟فکر من این است که رفتارها نیز می توانند کاملاً داخلی باشند. ما به دنبال رفتارهای خارج از کشور از تماس گیرنده هستیم. این تمایز ممکن است در طول برنامه نویسی "اقدام زنده" دشوار باشد. همچنین ، "Exit Point" مفهوم خوبی به آن دارد که نشان می دهد ما زمینه یک واحد کار را ترک می کنیم و به متن آزمایش باز می گردیم. رفتارها ممکن است کمی روانتر از آن باشد. این گفت ، من مطمئن نیستم. شاید این در نسخه چهارم کتاب تست واحد هنر من تغییر کند ...

در اینجا یک نمونه کد سریع از یک واحد ساده کار آورده شده است.

محاصره کردن جمع = (شماره) => <محاصره کردن [a, b] = شماره.شکاف(','); محاصره کردن نتیجه = عدد.تجزیه(a, 10) + عدد.تجزیه(b, 10); برگشت نتیجه;>;

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

unit-of-work1.1.png

من از "جمع (اعداد)" به عنوان نقطه ورود استفاده کردم و نه "اعداد" زیرا نقطه ورود امضای عملکرد است. پارامترها زمینه یا ورودی است که از طریق نقطه ورود ارائه می شود.

در اینجا تنوع این ایده وجود دارد:

یک واحد کار دارای نقاط ورود و نقاط خروج است:

اجازه دهید جمع = 0; محاصره کردن کلبه = () => <برگشت جمع;>; محاصره کردن جمع = (شماره) => <محاصره کردن [a, b] = شماره.شکاف(','); محاصره کردن نتیجه = عدد.تجزیه(a, 10) + عدد.تجزیه(b, 10); جمع += نتیجه; برگشت نتیجه;>; مدول.صادر کردن = <جمع, کلبه>;

این نسخه جدید از دو نقطه خروج است. این دو کار را انجام می دهد:

1. یک مقدار را برمی گرداند

2. عملکرد جدیدی دارد: از کل مبلغ در حال اجرا است. این وضعیت ماژول را به گونه ای قابل توجه (از طریق TotalSofar ()) از تماس گیرنده نقطه ورود تنظیم می کند.

unit-of-work1.2.png

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

همچنین این بدان معنی است که من به احتمال زیاد در اینجا دو تست واحد مختلف می نویسم: یکی برای هر نقطه خروج. خیلی زود ما دقیقاً همین کار را خواهیم کرد.

در مورد Totalsofar () چطور؟آیا این نیز یک نقطه ورود است؟بله ، می تواند باشد. در یک تست جداگانهمن می توانم آزمایشی بنویسم که ثابت کند فراخوانی Totalsofar () بدون شروع قبل از بازگشت تماس 0. باز می گردد 0. این امر باعث می شود واحد کار کوچک خود باشد. و کاملاً خوب خواهد بود. غالباً یک واحد کار (جمع ()) می تواند از واحدهای کوچکتر ساخته شود. این جایی است که می توانیم ببینیم که چگونه دامنه تست های ما می تواند تغییر کرده و جهش یابد ، اما ما هنوز هم می توانیم آن را با نقاط ورود و نقاط خروج تعریف کنیم.

نقاط ورود همیشه در جایی است که آزمایش باعث ایجاد واحد کار می شود. شما می توانید چندین نقطه ورود به یک واحد کار داشته باشید که هر یک توسط مجموعه ای متفاوت از تست ها استفاده می شود.

یک یادداشت جانبی در مورد طراحی

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

ما اغلب این دو را با هم ترکیب می کنیم اما موارد بسیاری وجود دارد که جدا کردن آنها ممکن است انتخاب طراحی بهتری باشد. این پست در درجه اول مربوط به طراحی نیست ، اما من از شما می خواهم که اطلاعات بیشتری در مورد مفهوم جدایی فرمان-Query در وب سایت مارتین فاولر بخوانید: https://martinfowler. com/bliki/commandqueryseparation. html

نقاط خروج اغلب حاکی از الزامات و تست های جدید است و برعکس

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

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

بازگشت به کد:

در اینجا نسخه سوم این عملکرد وجود دارد:

محاصره کردن وینستون = نیاز("وینستون"); اجازه دهید جمع = 0; محاصره کردن کلبه = () => <برگشت جمع;>; محاصره کردن مروارید = () => <برگشت وینستون .خالق(<مرحله: "اطلاعات", حمل: جدید وینستون.حمل.کنسول()>);>; محاصره کردن متمرکز ساز = مروارید(); محاصره کردن جمع = (شماره) => <محاصره کردن [a, b] = شماره.شکاف(','); متمرکز ساز.اطلاعات( "این یک خروجی ورود به سیستم بسیار مهم است", <رده بندی اول: a, دوم: b>); محاصره کردن نتیجه = عدد.تجزیه(a, 10) + عدد.تجزیه(b, 10); جمع += نتیجه; برگشت نتیجه;>; مدول.صادر کردن = <کلبه, جمع>;

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

این نوع سوم نقطه خروج است: فراخوانی شخص ثالث. من همچنین دوست دارم آن را "فراخوانی وابستگی" بنامم.

وابستگی (شخص ثالث)

وابستگی چیزی است که ما در طول آزمایش واحد کنترل کامل نداریم. یا چیزی که برای کنترل در یک آزمایش ، زندگی ما را بدبخت می کند تا از خواب برخاست و دوید ، حفظ ، تست را ثابت نگه داریم یا سریع انجام شود. برخی از مثالها شامل: loggers که به پرونده ها می نویسند ، چیزهایی که با شبکه صحبت می کنند ، کد کنترل شده توسط تیم های دیگر که ما نمی توانیم آنها را تغییر دهیم ، مؤلفه هایی که به دلیل نحوه عملکرد آنها مدت زمان بسیار طولانی (محاسبات ، موضوعات ، دسترسی به بانک اطلاعاتی) وبیشتر. قانون شست این است: "اگر بتوانم به طور کامل و به راحتی آنچه را انجام می دهم کنترل کنم ، و در حافظه اجرا می شود ، و سریع آن ، این یک وابستگی نیست". همیشه استثنائاتی از این قاعده وجود دارد ، اما این باید حداقل 80 ٪ موارد را به شما منتقل کند.

در اینجا نحوه ترسیم آن با هر سه نقطه خروج و دو نقطه ورود با هم آورده شده است:

unit-of-work3.png

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

آزمون در هر نقطه خروج

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

انواع نقطه خروج

ما دیده ایم که ما سه نوع مختلف از نتایج نهایی داریم:

بر اساس ارزش

function تابع فراخوانی شده یک مقدار مفید (تعریف نشده) را برمی گرداند. اگر این به زبان ایستا تر مانند جاوا یا C# بود ، می گوییم این یک عملکرد عمومی و غیر باطل است.

مستقر در دولت

§ تغییر قابل توجهی در حالت یا رفتار سیستم قبل و بعد از دعوت وجود دارد که می تواند بدون بازجویی از وضعیت خصوصی تعیین شود.(در مورد ما ، عملکرد WASCALLED () پس از تغییر حالت ، مقدار متفاوتی را برمی گرداند.)

شخص ثالث

§ یک تماس با یک سیستم شخص ثالث وجود دارد که آزمایش آن هیچ کنترلی ندارد. این سیستم شخص ثالث هیچ مقداری را برمی گرداند ، یا این مقدار نادیده گرفته می شود.(مثال: فراخوانی یک سیستم ورود به سیستم شخص ثالث که توسط شما نوشته نشده است و کد منبع آن را کنترل نمی کنید.)

تعریف الگوهای آزمون Xunit از نقاط ورود و خروج

الگوهای آزمون Xunit در مورد مفهوم ورودی ها و خروجی های مستقیم و ورودی ها و خروجی های غیرمستقیم بحث می کند. ورودی های مستقیم همان چیزی است که من دوست دارم آن را به نقاط ورودی بنامم. آن کتاب آن را "استفاده از درب جلو" یک جزء نامید. خروجی های غیرمستقیم در آن کتاب را می توان به عنوان دو نوع دیگر از نقاط خروج که ذکر کردم (تغییر دولت و فراخوانی شخص ثالث) تصور کرد. هر دو نسخه از این ایده ها به صورت موازی تکامل یافته اند ، اما ایده "واحد کار" فقط در این کتاب ظاهر می شود. واحد کار ، همراه با نقاط "ورود" و "خروج" برای من بسیار بیشتر است که استفاده از "ورودی ها و خروجی های مستقیم و غیرمستقیم". این را یک انتخاب سبک در مورد چگونگی آموزش مفهوم دامنه آزمون در نظر بگیرید. می توانید اطلاعات بیشتری در مورد الگوهای تست Xunit در Xunitpattes. com پیدا کنید

بیایید ببینیم که چگونه ایده ورود و خروج نقاط بر تعریف یک آزمون واحد تأثیر می گذارد.

تعریف به روز شده از یک آزمون واحد:

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

1. 2 نقطه خروج مختلف ، تکنیک های مختلف

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

· نقاط خروج مبتنی بر ارزش بازگشت (خروجی های مستقیم در "الگوهای XUNIT") از انواع نقطه خروج ، باید ساده ترین آزمایش باشد. شما یک نقطه ورود را تحریک می کنید ، چیزی را پس می گیرید ، مقدار بازگشت را بررسی می کنید.

· تست های مبتنی بر ایالت (خروجی های غیرمستقیم) معمولاً به ژیمناستیک کمی بیشتر نیاز دارند. شما با چیزی تماس می گیرید ، سپس یک تماس دیگر انجام می دهید تا چیز دیگری را بررسی کنید (یا دوباره چیز قبلی را صدا کنید) تا ببینید که آیا همه چیز طبق برنامه پیش رفته است یا خیر.

در یک وضعیت شخص ثالث (خروجی های غیرمستقیم) ما بیشترین حلقه را برای پرش از آن داریم. ما هنوز این ایده را مورد بحث قرار نداده ایم ، این جایی است که ما مجبور شده ایم از چیزهایی مانند اشیاء مسخره در تست های خود استفاده کنیم تا بتوانیم سیستم خارجی را با یک مورد که می توانیم در تست های خود کنترل و بازجویی کنیم ، جایگزین کنیم. من این ایده را بعداً در کتاب پوشش خواهم داد.

کدام نقاط خروج بیشترین مشکلات را ایجاد می کند؟

به عنوان یک قانون شست ، من سعی می کنم بیشتر آزمایشات خود را یا آزمایش های مبتنی بر ارزش یا مبتنی بر حالت حفظ کنم. من سعی می کنم اگر می توانم از تست های مبتنی بر مسخره جلوگیری کنم و معمولاً می توانم. در نتیجه من معمولاً بیش از 5 ٪ از آزمایشات خود را با استفاده از اشیاء مسخره برای تأیید ندارم. این نوع تست ها چیزها را پیچیده و حفظ قابلیت حفظ آن را دشوارتر می کند. هرچند که بعضی اوقات فرار وجود ندارد ، و ما در پست های آینده در مورد آنها بحث خواهیم کرد.

فارکس وکسب درامد...
ما را در سایت فارکس وکسب درامد دنبال می کنید

برچسب : نویسنده : مهدی اسدی بازدید : <-PostHit-> تاريخ : دوشنبه 13 شهريور 1402 ساعت: 4:44