تست های GO خود را برای استحکام و رهایی از آن زمان های مزاحم صیقل دهید

به قسمت نهایی سریال ما در رفع زمان های تست واحد GO خوش آمدید! در قسمت 1 ، ما با ناامیدی اولیه مقابله کردیم panic: test timed out
با SetReadDeadline
و کانال ها برای مشتری های مشتری. در قسمت 2 ، ما به پیچیدگی های آزمایش همزمان کبوتر می کنیم و پخش کننده را با آن قرار می دهیم sync.WaitGroup
و مدیریت مناسب دولت
اکنون ، ما با نگاهی به توابع مشترک ابزار و فرآیند مهم اولیه سازی سرور ، همه اینها را جمع می کنیم. این مناطق غالباً چالش های آزمایش منحصر به فرد خود را ارائه می دهند ، از اطمینان از اینکه عملیات فایل قوی است تا اطمینان حاصل شود که سرور شما هر بار قابل اعتماد است. سفر من با پروژه GO NetCat شامل تست های پالایش برای کارکردهایی است که سابقه چت را اداره می کنند و سرور بسیار قدرتمند آن را به دست می آورند.
تست توابع ابزار: پرونده I/O و اعلان های مشتری
توابع ابزار ممکن است ساده به نظر برسد ، اما وقتی با سیستم فایل در تعامل هستند یا اتصالات مشتری را مدیریت می کنند ، می توانند اشکالات ظریف یا تأخیرهای غیر منتظره را در صورت عدم آزمایش دقیق معرفی کنند.
TestSendChatHistory
: تسلط بر خواندن پرونده و نوشتن شبکه
در SendChatHistory
عملکرد در پروژه NetCat من وظیفه خواندن پیام های چت گذشته از یک پرونده و ارسال آنها به یک مشتری تازه متصل را دارد. آزمایش این کار به طور مؤثر نیاز به کنترل دقیق هر دو ورودی/خروجی پرونده (I/O) و نوشتن شبکه دارد.
تلاش های اولیه اغلب با موضوعاتی مانند:
- تست های حلق آویز اگر پرونده خالی بود یا وجود نداشت.
- ارسال پیام ناقص اگر نوشتن شبکه کند یا مسدود شده بود.
- مشکلات تأیید چندین خط تاریخ.
اصلاحات شامل ترکیبی از تکنیک هایی است که ما در مورد آنها بحث کردیم:
- رسیدگی به وجود پرونده: آزمون صریحاً بررسی می کند
SendChatHistory
رفتار وقتی پرونده تاریخ استdoesn't exist
بشر این امر به جای تصادف یا آویز ، رسیدگی به خطای برازنده (یا پیام “بدون تاریخ”) را تضمین می کند. -
sync.WaitGroup
برای تکمیل: کیSendChatHistory
در goroutine خاص خود اجرا می شود (همانطور که ممکن است در یک برنامه واقعی یا در طولHandleClient
اعدام) ، ما باید اطمینان حاصل کنیم که آزمون منتظر پایان آن است.sync.WaitGroup
برای تأیید Goroutine کار خود را انجام می دهد. - شبکه قوی با مهلت می خواند: خواندن چندین خط از تاریخ چت از
net.Pipe
به یک حلقه نیاز دارد. هر عملیات خوانده شده در این حلقه توسط محافظت می شودclient.SetReadDeadline(time.Now().Add(2 * time.Second))
بشر اگر سرور از ارسال اطلاعات زود هنگام یا در صورت تأخیر جلوگیری کند ، این تست را به طور نامحدود از آویزان جلوگیری می کند. حلقه سپس با لطفbreaks
در یک زمان یاio.EOF
(انتهای پرونده) ، به آزمایش اجازه می دهد تا چه چیزی را تأیید کند بود دریافت - جمع کردن محتوا با
strings.Builder
: به جای خواندن در یک بافر ثابت ، بارها و بارها ، با استفاده از astrings.Builder
برای جمع آوری محتوای دریافت شده ، تضمین می کند که تمام قسمت های تاریخ اسیر شده اند ، صرف نظر از اینکه تعداد شبکه ای از آن را می خواند. - پاکسازی کامل پرونده: همیشه
defer os.Remove(tmpFile.Name())
برای هر پرونده موقت ایجاد شده در طول آزمایش.
با استفاده از این شیوه ها ، TestSendChatHistory
به یک تأیید قوی از خواندن فایل ، نوشتن شبکه و رسیدگی به خطا تبدیل شد.
TestNotifyClients
: اطمینان از تحویل هدفمند
یکی دیگر از عملکردهای ابزار ، NotifyClients
، ممکن است مسئول ارسال پیام به زیر مجموعه مشتری ها باشد ، شاید به استثنای فرستنده. آزمایش این امر نیاز دارد:
- تنظیم چندین مشتری مسخره.
- ارسال پیام
- تأیید آن تنها مشتریان در نظر گرفته شده پیام را دریافت می کنند.
- اطمینان از دسترسی با ایمن به نقشه های مشتری مشترک (با استفاده از
models.Mu.Lock()
وتmodels.Mu.Unlock()
).
نکته اصلی در اینجا تنظیم و تأیید مناسب است ، که اغلب شامل آن است net.Pipe()
برای هر مشتری و سپس خواندن انتخابی از client
به پایان می رسد که چه کسی چه چیزی را بدست آورده است. اضافه کردن زمان به این خواندها بسیار مهم است ، همانطور که از محافظت مناسب از mutex در هنگام دسترسی برخوردار است models.Clients
نقشه
آزمایش اولیه سرور: اولین برداشت
در InitServer
عملکرد مطمئناً یکی از مهمترین قسمت های برنامه شما است. اگر سرور به درستی شروع نشود ، هیچ چیز دیگری مهم نیست. تست InitServer
قابل اعتماد به معنای:
- اطمینان از گوش دادن در درگاه صحیح.
- تأیید اینکه ورود به سیستم لازم یا ساختار پرونده را تنظیم می کند.
- تأیید آن می تواند اتصالات جدید مشتری را بپذیرد.
- اطمینان از ارسال پیام های خوش آمدید اولیه (مانند آرم و نام سریع).
- رسیدگی به خطاهای احتمالی (به عنوان مثال ، درگاه از قبل استفاده شده است).
من TestInitServer
در ابتدا شکست خورد زیرا انتظار نداشت سرور پیام “آرم” ارسال کند پیش از “نام سریع”. این نشان می دهد که چقدر مهم است که تست های شما به طور دقیق منعکس شود کامل جریان تعامل.
در اینجا چگونه TestInitServer
قوی ساخته شد:
- ساختار جدول آزمون: با استفاده از a
test table
اجازه می دهد تا چندین سناریو (راه اندازی موفقیت آمیز ، پورت در حال استفاده و غیره) به صورت تمیز در یک عملکرد واحد آزمایش شود. - ایجاد فایل آرم صریح: آزمایش اکنون ایجاد می کند
logo.txt
پرونده در تنظیمات تست. این تضمین می کند که سرور پرونده مورد انتظار را برای خواندن و ارسال به مشتری های جدید دارد. همچنین شامل می شودdefer os.Remove("logo.txt")
برای پاکسازی -
تأیید خواندن متوالی: در
validateFunc
برای راه اندازی موفق اکنون صریحاً خوانده می شودlogo
ابتدا ، سپسname prompt
بشر// Read and verify logo logo, err := reader.ReadString('\n') // ... error checks ... // Read and verify name prompt namePrompt, err := reader.ReadString(':') // ... error checks ...
این آینه رفتار واقعی سرور را نشان می دهد و از “سریع نام مورد انتظار ، جلوگیری می کند:” شکست.
-
net.DialTimeout
وتSetReadDeadline
: هنگام اتصال به سرور در حال اجرا ،net.DialTimeout
تضمین می کند که تلاش اتصال به طور نامحدود آویزان نیست. پس از اتصال ،conn.SetReadDeadline
برای اطمینان از عدم انتظار مشتری برای پیام های اولیه سرور بسیار مهم است. -
پاکسازی قوی: فراتر از پرونده ها ، تست های سرور باید هر پورت باز را تمیز کنند. در حالی که
InitServer
به طور معمول در یک محیط تولید به طور نامحدود اجرا می شود ، در یک آزمایش ، باید اطمینان حاصل کنید که به طرز فجیعی متوقف شده است یا اینکه گوروتین آن باقی نمی ماند. ساختار تست شامل مکانیسم هایی برای اطمینان از خروج سرور گوروتین است یا حداقل برای متوقف کردن پس از ادعاهای آزمون سیگنال داده می شود.
با انجام این تنظیمات ، TestInitServer
به دلیل سفارش پیام غیر منتظره برای تأیید آمادگی سرور ، از عدم موفقیت رفت.
غذای نهایی: درسهایی از سنگرها
در طول این سریال ، ما به بررسی مشکلات رایج آزمایش واحد GO و مهمتر از همه نحوه غلبه بر آنها پرداختیم. سفر من با آزمایشات پروژه NetCat چندین درس مهم را تقویت کرد:
-
هیچ
time.Sleep()
در تست ها (تقریباً هرگز): این رایج ترین منبع آزمایش های پوسته پوسته و غیرقابل اعتماد است. آن را با کانال ها جایگزین کنید ،sync.WaitGroup
، یاSetReadDeadline
برای انتظار قطعی -
زمان آغوش را در آغوش بگیرید: انتظار نامحدود را به خرابی های قابل پیش بینی تبدیل کنید.
SetReadDeadline
برایnet.Conn
وتtime.After
درselect
اظهارات بهترین دوستان شما هستند. - پاکسازی دقیق غیر قابل مذاکره است: اتصالات را ببندید ، پرونده های موقت را حذف کنید و قبل از آن همه وضعیت جهانی را دوباره تنظیم کنید هر یک اجرای آزمون. حالت مشترک اراده شما را گاز بگیرید
- واقعیت آزمون ، نه فقط مسیرهای ایده آل: قطع ارتباط ، پرونده های خالی و سفارشات پیام غیر منتظره را شبیه سازی کنید. آزمایشات شما باید آینه ای را نشان دهد که چگونه برنامه شما در واقع در طبیعت رفتار خواهد کرد.
- ردیابی پشته را بخوانید: این خروجی “وحشت: آزمایش به پایان رسیده” ، به ویژه ردیابی گوروتین ، نقشه گنج شما به اشکال است.
- اولویت بندی قابلیت اطمینان آزمون: تست های پوسته پوسته اعتماد به نفس را از بین می برد. زمان را به صورت مقدماتی سرمایه گذاری کنید تا آنها را قوی کنید. این سود سهام را در اشکال زدایی سریعتر و استقرار مطمئن تر پرداخت می کند.
امیدوارم این سریال بینش های ارزشمندی و راه حل های عملی را برای هر کسی که با تست های واحد Go تلاش می کند ، ارائه دهد. با استفاده از این اصول ، می توانید تجربه آزمایش خود را از منبع ناامیدی به یک ابزار قدرتمند برای ساختن برنامه های قابل اعتماد GO تبدیل کنید. آزمایش مبارک!