Skip to content

Commit

Permalink
gopls/internal/golang: add testcase handling for func with error returns
Browse files Browse the repository at this point in the history
This commit improves the handling of test cases for functions
that return an error as their last return value.

- A boolean field called "wantErr" is added to the test case
struct to indicate whether an error is expected.
- The error return value is now handled before comparing other
return values, ensuring correct error handling in test cases.

For golang/vscode-go#1594

Change-Id: Ib48f6b85b2fdad96cb7fb563b8bdbf17d692f569
Reviewed-on: https://go-review.googlesource.com/c/tools/+/623997
Reviewed-by: Robert Findley <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
h9jiang committed Nov 5, 2024
1 parent e5417d7 commit 6d27bba
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 13 deletions.
50 changes: 37 additions & 13 deletions gopls/internal/golang/addtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const testTmplString = `func {{.TestFuncName}}(t *testing.T) {
{{- end}}
}
{{- end}}
{{- /* Test cases struct declaration and empty initialization. */}}
tests := []struct {
name string // description of this test case
Expand All @@ -47,12 +48,18 @@ const testTmplString = `func {{.TestFuncName}}(t *testing.T) {
arg {{(index .Args 0).Type}}
{{- end}}
{{- range $index, $res := .Results}}
{{if eq $index 0}}want{{else}}want{{add $index 1}}{{end}} {{$res.Type}}
{{- /* TODO(hxjiang): check whether the last return type is error and handle it using field "wantErr". */}}
{{- if eq $res.Name "gotErr"}}
wantErr bool
{{- else if eq $index 0}}
want {{$res.Type}}
{{- else}}
want{{add $index 1}} {{$res.Type}}
{{- end}}
{{- end}}
}{
// TODO: Add test cases.
}
{{- /* Loop over all the test cases. */}}
for _, tt := range tests {
{{/* Got variables. */}}
Expand All @@ -66,14 +73,31 @@ const testTmplString = `func {{.TestFuncName}}(t *testing.T) {
{{- /* Input parameters. */ -}}
({{if eq (len .Args) 1}}tt.arg{{end}}{{if gt (len .Args) 1}}{{fieldNames .Args "tt.args."}}{{end}})
{{- if .Results}}
{{- /* Handles the returned error before the rest of return value. */}}
{{- $last := index .Results (add (len .Results) -1)}}
{{- if eq $last.Name "gotErr"}}
if gotErr != nil {
if !tt.wantErr {
t.Errorf("%s: {{$.FuncName}}() failed: %v", tt.name, gotErr)
}
return
}
if tt.wantErr {
t.Fatalf("%s: {{$.FuncName}}() succeeded unexpectedly", tt.name)
}
{{- end}}
{{- /* Compare the returned values except for the last returned error. */}}
{{- if or (and .Results (ne $last.Name "gotErr")) (and (gt (len .Results) 1) (eq $last.Name "gotErr"))}}
// TODO: update the condition below to compare got with tt.want.
{{- range $index, $res := .Results}}
{{- if ne $res.Name "gotErr"}}
if true {
t.Errorf("%s: {{$.FuncName}}() = %v, want %v", tt.name, {{.Name}}, tt.{{if eq $index 0}}want{{else}}want{{add $index 1}}{{end}})
}
{{- end}}
{{- end}}
{{- end}}
}
}
`
Expand Down Expand Up @@ -306,18 +330,18 @@ func AddTestForFunc(ctx context.Context, snapshot *cache.Snapshot, loc protocol.
}
}

errorType := types.Universe.Lookup("error").Type()
for i := range sig.Results().Len() {
if i == 0 {
data.Results = append(data.Results, field{
Name: "got",
Type: types.TypeString(sig.Results().At(i).Type(), qf),
})
} else {
data.Results = append(data.Results, field{
Name: fmt.Sprintf("got%d", i+1),
Type: types.TypeString(sig.Results().At(i).Type(), qf),
})
name := "got"
if i == sig.Results().Len()-1 && types.Identical(sig.Results().At(i).Type(), errorType) {
name = "gotErr"
} else if i > 0 {
name = fmt.Sprintf("got%d", i+1)
}
data.Results = append(data.Results, field{
Name: name,
Type: types.TypeString(sig.Results().At(i).Type(), qf),
})
}

var test bytes.Buffer
Expand Down
97 changes: 97 additions & 0 deletions gopls/internal/test/marker/testdata/codeaction/addtest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,100 @@ var fooNode = yourast.Node{}
+ }
+ }
+}
-- returnwitherror/returnwitherror.go --
package main

func OnlyErr() error {return nil} //@codeactionedit("OnlyErr", "source.addTest", return_only_error)
func StringErr() (string, error) {return "", nil} //@codeactionedit("StringErr", "source.addTest", return_string_error)
func MultipleStringErr() (string, string, string, error) {return "", "", "", nil} //@codeactionedit("MultipleStringErr", "source.addTest", return_multiple_string_error)

-- @return_only_error/returnwitherror/returnwitherror_test.go --
@@ -0,0 +1,22 @@
+package main_test
+
+func TestOnlyErr(t *testing.T) {
+ tests := []struct {
+ name string // description of this test case
+ wantErr bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ gotErr := main.OnlyErr()
+ if gotErr != nil {
+ if !tt.wantErr {
+ t.Errorf("%s: OnlyErr() failed: %v", tt.name, gotErr)
+ }
+ return
+ }
+ if tt.wantErr {
+ t.Fatalf("%s: OnlyErr() succeeded unexpectedly", tt.name)
+ }
+ }
+}
-- @return_string_error/returnwitherror/returnwitherror_test.go --
@@ -0,0 +1,27 @@
+package main_test
+
+func TestStringErr(t *testing.T) {
+ tests := []struct {
+ name string // description of this test case
+ want string
+ wantErr bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ got, gotErr := main.StringErr()
+ if gotErr != nil {
+ if !tt.wantErr {
+ t.Errorf("%s: StringErr() failed: %v", tt.name, gotErr)
+ }
+ return
+ }
+ if tt.wantErr {
+ t.Fatalf("%s: StringErr() succeeded unexpectedly", tt.name)
+ }
+ // TODO: update the condition below to compare got with tt.want.
+ if true {
+ t.Errorf("%s: StringErr() = %v, want %v", tt.name, got, tt.want)
+ }
+ }
+}
-- @return_multiple_string_error/returnwitherror/returnwitherror_test.go --
@@ -0,0 +1,35 @@
+package main_test
+
+func TestMultipleStringErr(t *testing.T) {
+ tests := []struct {
+ name string // description of this test case
+ want string
+ want2 string
+ want3 string
+ wantErr bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ got, got2, got3, gotErr := main.MultipleStringErr()
+ if gotErr != nil {
+ if !tt.wantErr {
+ t.Errorf("%s: MultipleStringErr() failed: %v", tt.name, gotErr)
+ }
+ return
+ }
+ if tt.wantErr {
+ t.Fatalf("%s: MultipleStringErr() succeeded unexpectedly", tt.name)
+ }
+ // TODO: update the condition below to compare got with tt.want.
+ if true {
+ t.Errorf("%s: MultipleStringErr() = %v, want %v", tt.name, got, tt.want)
+ }
+ if true {
+ t.Errorf("%s: MultipleStringErr() = %v, want %v", tt.name, got2, tt.want2)
+ }
+ if true {
+ t.Errorf("%s: MultipleStringErr() = %v, want %v", tt.name, got3, tt.want3)
+ }
+ }
+}

0 comments on commit 6d27bba

Please sign in to comment.