ماڈیول اسباق (2/5)
ٹیبل پر مبنی ٹیسٹ
ٹیبل پر چلنے والے ٹیسٹ گو کا محاوراتی نمونہ ہیں: N الگ TestThisSpecificCase فنکشنز لکھنے کے بجائے، آپ کیسز کے ٹکڑوں کا اعلان کرتے ہیں اور اعادہ کرتے ہیں۔ ایک دعویٰ بلاک ہے، اور ٹیسٹ ڈیٹا کو منطق سے الگ کر دیا گیا ہے۔
بیس پیٹرن
func TestAbs(t *testing.T) {
cases := []struct {
name string
in int
want int
}{
{"pos", 3, 3},
{"neg", -3, 3},
{"zero", 0, 0},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := Abs(tc.in); got != tc.want {
t.Errorf("Abs(%d) = %d; voglio %d", tc.in, got, tc.want)
}
})
}
}تین اجزاء:
- گمنام ڈھانچے کا ٹکڑا معمول کے فیلڈز کے ساتھ:
name، ان پٹ، متوقع آؤٹ پٹ (اور شاید ایک متوقع غلطی)۔ for _, tc := range cases— عملدرآمد لوپ۔t.Run(tc.name, func(t *testing.T) { ... })— ہر کیس اپنے نام کے ساتھ ایک ذیلی ٹیسٹ بن جاتا ہے۔
کیوں t.Run؟
t.Run ایک ذیلی ٹیسٹ بناتا ہے جس میں:
- انفرادی نام آؤٹ پٹ میں دکھایا گیا ہے:
TestAbs/pos,TestAbs/neg, ... - اس کا اپنا
t *testing.T: ایک معاملے میں ناکامی دوسرے کو نہیں روکتی (جب تک کہt.Fatalاستعمال نہ کیا جائے)۔ - کمانڈ لائن فلٹرنگ:
go test -run TestAbs/negصرف اسی صورت میں چلتا ہے۔ - اختیاری ہم آہنگی: متوازی کرنے کے لیے فنک کے اندر
t.Parallel()کو کال کریں۔
go test -v -run TestAbs/negمتوقع غلطیوں والے کیسز
cases := []struct {
name string
in string
want int
wantErr bool
}{
{"ok", "42", 42, false},
{"bad", "x", 0, true},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, err := Atoi(tc.in)
if (err != nil) != tc.wantErr {
t.Fatalf("err = %v, wantErr = %v", err, tc.wantErr)
}
if !tc.wantErr && got != tc.want {
t.Errorf("got %d, want %d", got, tc.want)
}
})
}لوپ بند ہونے کا نقصان (پری گو 1.22)
Go 1.22 سے پہلے کے ورژنز میں، tc متغیر کو مشترکہ کیا گیا تھا: t.Parallel() کو t.Run کے اندر کال کرنے سے تمام ذیلی ٹیسٹ اسی آخری کیس کے خلاف چلائے گئے۔ طے یہ تھا:
for _, tc := range cases {
tc := tc // local rebind (pre-1.22)
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
// ...
})
}مقدمات کا نام دینا
بہترین طرز عمل:
- ایک مختصر لیکن اشتعال انگیز نام:
"empty input","too large","negative"۔ - اگر آپ
-runکے ساتھ آسانی سے فلٹر کرنا چاہتے ہیں تو کوئی خالی جگہ نہیں ہے (یا انڈر سکور استعمال کریں)۔ - ہمیشہ ایک "خوشی کا راستہ" کیس، ایک "ایج" کیس (صفر، خالی) اور کم از کم ایک غلطی کا کیس شامل کریں۔
مشقیں
Abs (مثبت، منفی، صفر) کو جانچنے کے لیے 3 کیسز کے ساتھ آباد، ان اور وانٹ فیلڈز کے ساتھ گمنام ڈھانچے کے کیسز سلائس کی وضاحت کریں۔
3 کوششوں کے بعد حل دستیاب ہے۔
ہر کیس کو نامزد ذیلی ٹیسٹ میں تبدیل کرنے کے لیے t.Run کو tc.name کے ساتھ شامل کریں۔
3 کوششوں کے بعد حل دستیاب ہے۔
N علیحدہ ٹیسٹ فنکشنز پر ٹیبل پر چلنے والے پیٹرن کا بنیادی فائدہ کیا ہے؟
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) { ... })
}