اکنون که کد خود را به یک وضعیت پایدار رساندهاید (بسیار عالی!)، وقت آن است که به آن تست (Test) اضافه کنید. تست کردن کد در طول توسعه میتواند باگهایی را که ممکن است هنگام اعمال تغییرات وارد کد شوند، مشخص و برطرف کند. در این بخش، یک تست برای تابع Hello اضافه میکنید.
💡 نکته: این موضوع بخشی از یک آموزش چندبخشی است که با بخش «ساخت یک ماژول گو» آغاز میشود.
پشتیبانی داخلی زبان گو از تست واحد (Unit Testing)، تست کردن در حین توسعه را آسانتر میکند. بهطور خاص، با استفاده از کنوانسیونهای نامگذاری، پکیج testing در گو و دستور go test میتوانید به سرعت تستهای خود را بنویسید و اجرا کنید.
۱. در دایرکتوری greetings، فایلی به نام greetings_test.go ایجاد کنید. خاتمه یافتن نام یک فایل با _test.go_ به دستور go test میگوید که این فایل شامل توابع تست است.
۲. در فایل greetings_test.go کد زیر را بچسبانید (Paste کنید) و فایل را ذخیره کنید:
package greetings
import (
"testing"
"regexp"
)
// TestHelloName calls greetings.Hello with a name, checking
// for a valid return value.
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b`+name+`\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Errorf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty calls greetings.Hello with an empty string,
// checking for an error.
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Errorf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
در این کد، شما:
-
توابع تست را در همان پکیجی که کد مورد تست در آن قرار دارد پیادهسازی میکنید.
-
دو تابع تست برای تست کردن تابع
greetings.Helloایجاد میکنید. نام توابع تست فرم کلیTestNameرا دارند، که در آنNameدرباره آن تست خاص توضیح میدهد. همچنین توابع تست یک اشارهگر (Pointer) به نوعtesting.Tاز پکیجtestingرا به عنوان پارامتر دریافت میکنند. شما از متدهای این پارامتر برای گزارشدهی و ثبت لوگ از تست خود استفاده میکنید. -
دو تست را پیادهسازی میکنید:
-
TestHelloName: تابعHelloرا فراخوانی کرده و مقداری را برای نام پاس میدهد که تابع باید بتواند بر اساس آن یک پیام پاسخ معتبر بازگرداند. اگر فراخوانی با خطا مواجه شود یا پیام پاسخ غیرمنتظره باشد (شامل نامی که ارسال کردهاید نباشد)، از متدErrorfپارامترtبرای چاپ پیام در کنسول استفاده میکنید. -
TestHelloEmpty: تابعHelloرا با یک رشته خالی فراخوانی میکند. این تست برای اطمینان از درست کار کردن مدیریت خطا طراحی شده است. اگر فراخوانی یک رشته غیرخالی بازگرداند یا هیچ خطایی برنگرداند، از متدErrorfپارامترtبرای چاپ پیام در کنسول استفاده میکنید.
-
۳. در خط فرمان درون دایرکتوری greetings، دستور go test را برای اجرای تست اجرا کنید.
دستور go test توابع تست (که نام آنها با Test شروع میشود) را در فایلهای تست (که نام آنها با _test.go_ تمام میشود) اجرا میکند. میتوانید پرچم v- را اضافه کنید تا خروجی دقیقتری (Verbose) دریافت کنید که تمام تستها و نتایج آنها را لیست کند.
تستها باید پاس شوند:
$ go test
PASS
ok example.com/greetings 0.364s
$ go test -v
=== RUN TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok example.com/greetings 0.372s
۴. تابع greetings.Hello را عمداً خراب کنید تا نتیجه یک تست مردود (Failing test) را ببینید.
تابع تست TestHelloName مقدار بازگشتی را برای نامی که به عنوان پارامتر تابع Hello مشخص کردهاید بررسی میکند. برای مشاهده نتیجه یک تست ناموفق، تابع greetings.Hello را طوری تغییر دهید که دیگر شامل نام نباشد.
در فایل greetings/greetings.go کد زیر را به جای تابع Hello بچسبانید (توجه داشته باشید که خطوط تغییر یافته باعث میشوند مقداری که تابع بازمیگرداند تغییر کند، انگار که آرگومان name به طور تصادفی حذف شده است):
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
// message := fmt.Sprintf(randomFormat(), name)
message := fmt.Sprint(randomFormat())
return message, nil
}
۵. در خط فرمان درون دایرکتوری greetings، دستور go test را برای اجرای تست اجرا کنید.
این بار دستور go test را بدون پرچم v- اجرا کنید. خروجی فقط شامل نتایج تستهایی خواهد بود که مردود شدهاند، که وقتی تستهای زیادی دارید بسیار مفید است. تست TestHelloName باید رد شود، در حالی که TestHelloEmpty همچنان پاس میشود.
$ go test
--- FAIL: TestHelloName (0.00s)
greetings_test.go:15: Hello("Gladys") = "Hail, %v! Well met!", <nil>, want match for `\bGladys\b`, nil
FAIL
exit status 1
FAIL example.com/greetings 0.182s
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: منبع مستندات