Skip to content

Commit 49dfdf5

Browse files
Tito Linscweill
Tito Lins
andauthored
Add TemplateData to opts (#140)
Co-authored-by: Charles Weill <c@weill.io>
1 parent f15877a commit 49dfdf5

File tree

13 files changed

+182
-11
lines changed

13 files changed

+182
-11
lines changed

gotests.go

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Options struct {
2828
Template string // Name of custom template set
2929
TemplateDir string // Path to custom template set
3030
TemplateParams map[string]interface{} // Custom external parameters
31+
TemplateData [][]byte // Data slice for templates
3132
}
3233

3334
// A GeneratedTest contains information about a test file with generated tests.
@@ -124,6 +125,7 @@ func generateTest(src models.Path, files []models.Path, opt *Options) (*Generate
124125
Template: opt.Template,
125126
TemplateDir: opt.TemplateDir,
126127
TemplateParams: opt.TemplateParams,
128+
TemplateData: opt.TemplateData,
127129
})
128130
if err != nil {
129131
return nil, fmt.Errorf("output.Process: %v", err)

gotests/process/process.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,18 @@ const (
2323

2424
// Set of options to use when generating tests.
2525
type Options struct {
26-
OnlyFuncs string // Regexp string for filter matches.
27-
ExclFuncs string // Regexp string for excluding matches.
28-
ExportedFuncs bool // Only include exported functions.
29-
AllFuncs bool // Include all non-tested functions.
30-
PrintInputs bool // Print function parameters as part of error messages.
31-
Subtests bool // Print tests using Go 1.7 subtests
32-
Parallel bool // Print tests that runs the subtests in parallel.
33-
WriteOutput bool // Write output to test file(s).
34-
Template string // Name of custom template set
35-
TemplateDir string // Path to custom template set
36-
TemplateParamsPath string // Path to custom parameters json file(s).
26+
OnlyFuncs string // Regexp string for filter matches.
27+
ExclFuncs string // Regexp string for excluding matches.
28+
ExportedFuncs bool // Only include exported functions.
29+
AllFuncs bool // Include all non-tested functions.
30+
PrintInputs bool // Print function parameters as part of error messages.
31+
Subtests bool // Print tests using Go 1.7 subtests
32+
Parallel bool // Print tests that runs the subtests in parallel.
33+
WriteOutput bool // Write output to test file(s).
34+
Template string // Name of custom template set
35+
TemplateDir string // Path to custom template set
36+
TemplateParamsPath string // Path to custom parameters json file(s).
37+
TemplateData [][]byte // Data slice for templates
3738
}
3839

3940
// Generates tests for the Go files defined in args with the given options.
@@ -98,6 +99,7 @@ func parseOptions(out io.Writer, opt *Options) *gotests.Options {
9899
Template: opt.Template,
99100
TemplateDir: opt.TemplateDir,
100101
TemplateParams: templateParams,
102+
TemplateData: opt.TemplateData,
101103
}
102104
}
103105

gotests_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"go/types"
77
"io/ioutil"
88
"path"
9+
"path/filepath"
910
"regexp"
1011
"runtime"
1112
"strings"
@@ -28,6 +29,7 @@ func TestGenerateTests(t *testing.T) {
2829
templateDir string
2930
template string
3031
templateParamsPath string
32+
templateData [][]byte
3133
}
3234
tests := []struct {
3335
name string
@@ -725,6 +727,14 @@ func TestGenerateTests(t *testing.T) {
725727
wantNoTests: true,
726728
wantErr: true,
727729
},
730+
{
731+
name: "With templateData",
732+
args: args{
733+
srcPath: `testdata/test004.go`,
734+
templateData: mustLoadExternalTemplateDir(t, "testdata/templatedata/"),
735+
},
736+
want: mustReadAndFormatGoFile(t, "testdata/goldens/function_with_return_value_template_data.go"),
737+
},
728738
}
729739
tmp, err := ioutil.TempDir("", "gotests_test")
730740
if err != nil {
@@ -752,6 +762,7 @@ func TestGenerateTests(t *testing.T) {
752762
TemplateDir: tt.args.templateDir,
753763
Template: tt.args.template,
754764
TemplateParams: params,
765+
TemplateData: tt.args.templateData,
755766
})
756767
if (err != nil) != tt.wantErr {
757768
t.Errorf("%q. GenerateTests(%v) error = %v, wantErr %v", tt.name, tt.args.srcPath, err, tt.wantErr)
@@ -816,6 +827,31 @@ func loadExternalJsonFile(file string) (map[string]interface{}, error) {
816827
return params, err
817828
}
818829

830+
func mustLoadExternalTemplateDir(t *testing.T, dir string) [][]byte {
831+
files, err := ioutil.ReadDir(dir)
832+
if err != nil {
833+
t.Fatalf("ioutil.ReadDir: %v", err)
834+
}
835+
836+
templateData := make([][]byte, 0)
837+
838+
for _, f := range files {
839+
filePath := filepath.Join(dir, f.Name())
840+
templateData = append(templateData, mustLoadExternalTemplateFile(t, filePath))
841+
}
842+
843+
return templateData
844+
}
845+
846+
func mustLoadExternalTemplateFile(t *testing.T, file string) []byte {
847+
buf, err := ioutil.ReadFile(file)
848+
if err != nil {
849+
t.Fatalf("loading external template file: %v", err)
850+
}
851+
852+
return buf
853+
}
854+
819855
func toSnakeCase(s string) string {
820856
var res []rune
821857
for _, r := range []rune(s) {

internal/output/output.go

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Options struct {
2121
Template string
2222
TemplateDir string
2323
TemplateParams map[string]interface{}
24+
TemplateData [][]byte
2425
}
2526

2627
func Process(head *models.Header, funcs []*models.Function, opt *Options) ([]byte, error) {
@@ -34,6 +35,8 @@ func Process(head *models.Header, funcs []*models.Function, opt *Options) ([]byt
3435
if err != nil {
3536
return nil, fmt.Errorf("loading custom templates of name: %v", err)
3637
}
38+
} else if opt != nil && opt.TemplateData != nil {
39+
render.LoadFromData(opt.TemplateData)
3740
}
3841

3942
tf, err := ioutil.TempFile("", "gotests_")

internal/render/render.go

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ func init() {
3030
}
3131
}
3232

33+
// LoadFromData allows to load from a data slice
34+
func LoadFromData(templateData [][]byte) {
35+
initEmptyTmpls()
36+
for _, d := range templateData {
37+
tmpls = template.Must(tmpls.Parse(string(d)))
38+
}
39+
}
40+
3341
// LoadCustomTemplates allows to load in custom templates from a specified path.
3442
func LoadCustomTemplates(dir string) error {
3543
initEmptyTmpls()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package testdata
2+
3+
import "testing"
4+
5+
func TestFoo4(t *testing.T) {
6+
testCases := []struct {
7+
name string
8+
want bool
9+
}{
10+
// TODO: Add test cases.
11+
}
12+
for _, tt := range testCases {
13+
if got := Foo4(); got != tt.want {
14+
t.Errorf("%q. Foo4() = %v, want %v", tt.name, got, tt.want)
15+
}
16+
}
17+
}

testdata/templatedata/call.tmpl

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{define "call"}}{{with .Receiver}}{{if not .IsStruct}}tt.{{end}}{{Receiver .}}.{{end}}{{.Name}}({{range $i, $el := .Parameters}}{{if $i}}, {{end}}{{if not .IsWriter}}tt.args.{{end}}{{Param .}}{{if .Type.IsVariadic}}...{{end}}{{end}}){{end}}

testdata/templatedata/function.tmpl

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{{define "function"}}
2+
{{- $f := .}}
3+
4+
func {{.TestName}}(t *testing.T) {
5+
{{- with .Receiver}}
6+
{{- if .IsStruct}}
7+
{{- if .Fields}}
8+
type fields struct {
9+
{{- range .Fields}}
10+
{{Field .}} {{.Type}}
11+
{{- end}}
12+
}
13+
{{- end}}
14+
{{- end}}
15+
{{- end}}
16+
{{- if .TestParameters}}
17+
type args struct {
18+
{{- range .TestParameters}}
19+
{{Param .}} {{.Type}}
20+
{{- end}}
21+
}
22+
{{- end}}
23+
testCases := []struct {
24+
name string
25+
{{- with .Receiver}}
26+
{{- if and .IsStruct .Fields}}
27+
fields fields
28+
{{- else}}
29+
{{Receiver .}} {{.Type}}
30+
{{- end}}
31+
{{- end}}
32+
{{- if .TestParameters}}
33+
args args
34+
{{- end}}
35+
{{- range .TestResults}}
36+
{{Want .}} {{.Type}}
37+
{{- end}}
38+
{{- if .ReturnsError}}
39+
wantErr bool
40+
{{- end}}
41+
}{
42+
// TODO: Add test cases.
43+
}
44+
for {{if (or .Subtests (not .IsNaked))}} _, tt := {{end}} range testCases {
45+
{{- if .Subtests }}t.Run(tt.name, func(t *testing.T) { {{- end -}}
46+
{{- with .Receiver}}
47+
{{- if .IsStruct}}
48+
{{Receiver .}} := {{if .Type.IsStar}}&{{end}}{{.Type.Value}}{
49+
{{- range .Fields}}
50+
{{.Name}}: tt.fields.{{Field .}},
51+
{{- end}}
52+
}
53+
{{- end}}
54+
{{- end}}
55+
{{- range .Parameters}}
56+
{{- if .IsWriter}}
57+
{{Param .}} := &bytes.Buffer{}
58+
{{- end}}
59+
{{- end}}
60+
{{- if and (not .OnlyReturnsError) (not .OnlyReturnsOneValue) }}
61+
{{template "results" $f}} {{template "call" $f}}
62+
{{- end}}
63+
{{- if .ReturnsError}}
64+
if {{if .OnlyReturnsError}} err := {{template "call" $f}}; {{end}} (err != nil) != tt.wantErr {
65+
t.Errorf("{{template "message" $f}} error = %v, wantErr %v", {{template "inputs" $f}} err, tt.wantErr)
66+
{{- if .TestResults}}
67+
{{if .Subtests }}return{{else}}continue{{end}}
68+
{{- end}}
69+
}
70+
{{- end}}
71+
{{- range .TestResults}}
72+
{{- if .IsWriter}}
73+
if {{Got .}} := {{Param .}}.String(); {{Got .}} != tt.{{Want .}} {
74+
{{- else if .IsBasicType}}
75+
if {{if $f.OnlyReturnsOneValue}}{{Got .}} := {{template "inline" $f}}; {{end}} {{Got .}} != tt.{{Want .}} {
76+
{{- else}}
77+
if {{if $f.OnlyReturnsOneValue}}{{Got .}} := {{template "inline" $f}}; {{end}} !reflect.DeepEqual({{Got .}}, tt.{{Want .}}) {
78+
{{- end}}
79+
t.Errorf("{{template "message" $f}} {{if $f.ReturnsMultiple}}{{Got .}} {{end}}= %v, want %v", {{template "inputs" $f}} {{Got .}}, tt.{{Want .}})
80+
}
81+
{{- end}}
82+
{{- if .Subtests }} }) {{- end -}}
83+
}
84+
}
85+
86+
{{end}}

testdata/templatedata/header.tmpl

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{define "header"}}
2+
{{range .Comments}}{{.}}
3+
{{end}}
4+
package {{.Package}}
5+
6+
import (
7+
{{range .Imports}}{{.Name}} {{.Path}}
8+
{{end}}
9+
)
10+
{{end}}

testdata/templatedata/inline.tmpl

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{define "inline"}} {{template "call" .}} {{end}}

testdata/templatedata/inputs.tmpl

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{define "inputs"}}{{$f := .}}{{if not .Subtests}}tt.name, {{end}}{{if $f.PrintInputs}}{{range $f.Parameters}}tt.args.{{Param .}}, {{end}}{{end}}{{end}}

testdata/templatedata/message.tmpl

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{{define "message" -}}
2+
{{if not .Subtests}}%q. {{end}}{{with .Receiver}}{{.Type.Value}}.{{end}}{{.Name}}({{if .PrintInputs}}{{range $i, $el := .Parameters}}{{if $i}}, {{end}}%v{{end}}{{end}})
3+
{{- end}}

testdata/templatedata/results.tmpl

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{define "results"}} {{range $i, $el := .Results}}{{if $i}}, {{end}}{{Got .}}{{end}}{{if .ReturnsError}}, err{{end}} {{if or .Results .ReturnsError}} := {{end}} {{end}}

0 commit comments

Comments
 (0)