مهدی خانزادی
۵ تیر ۱۴۰۵
در این قسمت با یونیت تست در گولنگ آشنا میشویم و یاد میگیریم چطور برای کد خودمان تست بنویسیم.
یونیت تست, پایهترین نوع تست برای کنترل عملکرد صحیح کد است. اگر یک هرم برای انواع مختلف تست داشته باشیم, یونیت تست در پایین ترین قسمت این هرم قرار میگیرد.
همانطور که میبینیم یونیت تست در پایین ترین سطح هرم قرار دارد بدین معنی که معمولا اولین نوع تستی که شما باید بنویسید یونیت تست است. سطح مقطع هرم نمایانگر حجم تست است. پایین هرم پهن تر از بالای آن است و رفته رفته بالای هرم جمع تر و کوچکتر میشود. در اکثر مواقع حجم یونیت تست ها از تمام تست های دیگر بیشتر است.
در گولنگ برای نوشتن یونیت تست و اجرای آن نیاز به نصب ابزارهای جداگانه ندارید و تنها با استفاده از استاندارد پکیج های گولنگ میتوانید تست های خود را بنویسید و سپس با خط فرمان گولنگ آنها را اجرا کنید.
فرض کنید یک کد برای جمع اعداد صحیح به صورت زیر داریم و این کد درون فایل sum.go قرار دارد:
در گولنگ, فایل های تست دارای نام با پسوند _test هستند. بدینصورت اگر کدهای ما درون فایل sum.go قرارداشته باشند, تست های ما درون فایلی با نام sum_test.go قرار خواهند گرفت. هر تست یک تابع است که نام آن با Test شروع و دارای پارامتری از نوع *testing.T است.
برای کد بالا میتوانیم درون فایل sum_test.go تست خود را به صورت زیر تست بنویسیم:
برای اجرای تمامی تست ها میتوانیم از دستور go test ./… استفاده کنیم و برای اجرای یک تست خاص میتوانیم نام تست را با استفاده از -run مشخص کنیم به عنوان مثال در اینجا میتوان از go test -run ^TestSum$ ./... استفاده کرد که TestSum نمایانگر نام تست مورد نظر است.
با پاس دادن ./… مشخص میکنیم که تمامی گولنگ باید دایرکتوری فعلی و تمامی ساب دایرکتوری ها را به دنبال تست بگردد و در صورت پیدا کردن, آن را اجرا کند.
با اجرا کردن go test -run ^TestSum$ ./... تست ما اجرا میشود و در صورتی که پاس شود نتیجه ای مانند زیر را نمایش میدهد:
میتوانیم تست های بیشتری اضافه کنیم. مثلا دو تست داشته باشیم یکی حالتی که یک عدد به پاس میدیم و یکی حالتی که چندین عدد به این تابع به عنوان ورودی میدیم:
sumدرون*testing.T متدهای زیر را میتوانیم برای گزارش خطا استفاده کنیم:
Log : پارامترهای داده شده را در خروجی مینویسد.Logf : همانند Log پارامتر های داده شده را در خروجی مینویسد اما این قابلیت را به ما میدهد تا از فرمت های متنی برای نوشتن در خروجی استفاده کنیم.Errorf : با فراخوانی متد Logf اطلاعات مورد نظر ما را در خروجی مینویسد و سپس متد Fail را فراخوانی میکند.Error : با فراخوانی Log اطلاعات را در خروجی مینویسد و سپس متد Fail را فراخوانی میکند.Fail : تابعی که تست را انجام میدهد به عنوان fail شده علامت گذاری میکند. اجرا شدن تست ها ادامه پیدا میکند.FailNow : تابع فعلی که تست را انجام میدهد به عنوان fail شده علامت گذاری میکند و اجرا شدن باقی دستورات را به صورت آنی پایان میدهد (os.Exit را اجرا میکند پس هیچ دستوری بعد از FaileNow اجرا نمیشود حتی دستوراتی که defer شده اند اجرا نخواهند شد)Fatal : ابتدا Log و سپس FailNow را فراخوانی میکند. مشابه Error عمل میکند با این تفاوت که اجرا شدن تست ها ادامه پیدا نمیکند و به صورت آنی متوقف می شوند.Fatalf : ابتدا Logf و سپس FailNow را فراخوانی میکند. مشابه Errorf عمل میکند با این تفاوت که اجرا شدن تست ها ادامه پیدا نمیکند و به صورت آنی متوقف میشوند.تایپ T توابع کاربردی بیشتری دارد که میتونید آنها را درون استاندارد پکیج ببینید.
تیبل تست یا تست مبتنی بر جدول, یک الگوی استاندارد است که به جای نوشتن توابع تکراری برای هر حالت تست, داده های ورودی و خروجی مورد انتظار را در قالب یک آرایه یا اسلایس تعریف میکنیم و سپس به سادگی با یک حلقه روی عناصر این آرایه حرکت کرده و خروجی را بررسی میکنیم.
کد بالا را با روش table-driven میتوان به صورت زیر بازنویسی کرد:
اگر تیبل تست های ما زیاد باشند (بیشتر از دو یا سه تست برای مثال) در صورتی که پاس نشوند (pass), پیدا کردن اینکه کدامیک از تیبل تست ها پاس نشده است سخت است. با استفاده از t.Run در این مواقع میتوانیم هر کدام از تست ها را به صورت یک زیر تست (subtest) اجرا کنیم تا در خروجی دقیقا مشخص شود کدام تست به مشکل خورده است.
کد بالا را میتوانیم به صورت زیر بازنویسی کنیم:
با اجرا کردن تست بالا, هر ساب تست به صورت جداگانه اجرا و نتیجه ی آن در خروجی نمایش داده میشود:
برای اینکه نتیجهی هر تست را به صورت جداگانه ببینید, باید فلگ -v را استفاده کنید.
برای اجرای تست ها به صورت همزمان میتوان در ابتدای هر تست متد t.Parallel() را فراخوانی کرد. بدین صورت تست ها به صورت موازی اجرا خواهند شد و زمان اجرا شدن تست ها ممکن است به صورت چشمگیری کاهش پیدا کند.
کد بالا را میتوان به شکل زیر بازنویسی کرد:
نکته: زمانی که تست ها به صورت موازی اجرا میشوند, ممکن است ترتیب آنها در هر بار اجرا متفاوت باشد.
کدهای این قسمت را میتوانید درون گیت هاب نیز ببینید.
قسمت قبل: کانتکست (context) | گولنگ به زبان ساده
قسمت بعد: استاندارد پکیج time | گولنگ به زبان ساده