ప్రధాన కంటెంట్‌కు వెళ్లండి
మాడ్యూల్ 9 · 5లో పాఠం 2కోర్సులో 42/50~14 min
మాడ్యూల్ పాఠాలు (2/5)

టేబుల్ ఆధారిత పరీక్షలు

టేబుల్ ఆధారిత పరీక్షలు Go యొక్క ఇడియోమాటిక్ ప్యాటర్న్: N వేరుగా TestThisSpecificCase ఫంక్షన్‌లను వ్రాయడానికి బదులుగా, మీరు కేసుల స్లైస్‌ను ప్రకటించి, పునరావృతం చేయండి. ఒక నిర్థారణ బ్లాక్ ఉంది మరియు పరీక్ష డేటా లాజిక్ నుండి వేరు చేయబడింది.

బేస్ నమూనా

Go
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)
            }
        })
    }
}

మూడు పదార్థాలు:

  1. సాధారణ ఫీల్డ్‌లతో అజ్ఞాత నిర్మాణం యొక్క స్లైస్: name, ఇన్‌పుట్‌లు, ఊహించిన అవుట్‌పుట్ (మరియు బహుశా ఊహించిన లోపం కావచ్చు).
  2. for _, tc := range cases — అమలు లూప్.
  3. 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()కి కాల్ చేయండి.
Bash
go test -v -run TestAbs/neg

ఆశించిన లోపాలతో కేసులు

Go
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.Run లోపల t.Parallel()కి కాల్ చేయడం వలన అన్ని ఉప-పరీక్షలు అదే చివరి సందర్భంలో అమలు చేయబడ్డాయి. పరిష్కారం ఇలా ఉంది:

Go
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తో సులభంగా ఫిల్టర్ చేయాలనుకుంటే ఖాళీలు లేవు (లేదా అండర్‌స్కోర్‌లను ఉపయోగించండి).
  • ఎల్లప్పుడూ "హ్యాపీ పాత్" కేస్, "ఎడ్జ్" కేస్ (సున్నా, ఖాళీ) మరియు కనీసం ఒక ఎర్రర్ కేస్‌ని చేర్చండి.

వ్యాయామాలు

వ్యాయామం#go.m9.l2.e1
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

అబ్స్ (పాజిటివ్, నెగటివ్, జీరో) పరీక్షించడానికి 3 కేసులతో నిండిన మరియు కావలసిన ఫీల్డ్‌లతో అనామక నిర్మాణం యొక్క కేస్ స్లైస్‌ను నిర్వచించండి.

ఎడిటర్ లోడ్ అవుతోంది…

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది

వ్యాయామం#go.m9.l2.e2
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

ప్రతి కేసును పేరున్న ఉప-పరీక్షగా మార్చడానికి t.Runని tc.nameతో జోడించండి.

ఎడిటర్ లోడ్ అవుతోంది…

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది

Quiz#go.m9.l2.e3
సిద్ధంగా ఉంది

N ప్రత్యేక టెస్ట్ ఫంక్షన్‌లపై పట్టిక-ఆధారిత నమూనా యొక్క ప్రధాన ప్రయోజనం ఏమిటి?

Go
for _, tc := range cases {
  t.Run(tc.name, func(t *testing.T) { ... })
}
సమాధాన ఎంపికలు