From 7cd9fbbb80a37d0bd59740d8149f0c245482d244 Mon Sep 17 00:00:00 2001 From: Corin Lawson Date: Fri, 22 Mar 2024 20:04:14 +1100 Subject: [PATCH 1/4] chore: improve readability of test in GH actions Prior to this change, the test results are long and hard to see when one test ends and another starts. This change introduces gotestfmt tool which format go test output into coloured, collapsible sections. Also, the original JSON output is uploaded in case of any issues, along with the raw coverage data. --- .github/workflows/test.yml | 20 ++- example_test.go | 7 + go.sum | 1 + mod_test.go | 76 ++++++++++ testdata/example.txt | 285 +++++++++++++++++++++++++++++++++++++ 5 files changed, 386 insertions(+), 3 deletions(-) create mode 100644 mod_test.go create mode 100644 testdata/example.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 249ba45..ab575b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,12 +19,18 @@ jobs: - name: Tidy run: go mod tidy && git diff --exit-code + - name: Install gotestfmt + uses: gotesttools/gotestfmt-action@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Test run: | + set -euo pipefail mkdir -p "${{ runner.temp }}/covdata" - go test -v -cover ./... -test.gocoverdir="${{ runner.temp }}/covdata" - go tool covdata percent -i="${{ runner.temp }}/covdata" + go test -v -cover ./... -json -test.gocoverdir="${{ runner.temp }}/covdata" 2>&1 | tee "${{ runner.temp }}/test.log" | gotestfmt go tool covdata textfmt -o "${{ runner.temp }}/coverage.out" -i="${{ runner.temp }}/covdata" + go tool covdata percent -i="${{ runner.temp }}/covdata" - name: Coverage report uses: ncruces/go-coverage-report@v0 @@ -32,7 +38,15 @@ jobs: coverage-file: "${{ runner.temp }}/coverage.out" report: true chart: true - amend: true if: | github.event_name == 'push' continue-on-error: true + + - name: Upload test artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-logs + path: | + ${{ runner.temp }}/test.log + ${{ runner.temp }}/coverage.out diff --git a/example_test.go b/example_test.go index 6b7e34c..29ddf75 100644 --- a/example_test.go +++ b/example_test.go @@ -47,6 +47,7 @@ func (m *mockCache) Load(keys ...string) { var UnusedCache func(*mockCache) = nil func ExampleUnusedCache() { + // See ./testdata/example.txt for a full example. t := &exampleT{} // or any testing.TB, your test does not create this // 1. Create a mock object. var cache Cache = vermock.New(t, UnusedCache) @@ -66,6 +67,7 @@ func ExpectDelete(delegate func(t testing.TB, key string)) func(*mockCache) { } func Example_pass() { + // See ./testdata/example.txt for a full example. t := &exampleT{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, @@ -99,6 +101,7 @@ func Example_pass() { } func Example_unmetExpectation() { + // See ./testdata/example.txt for a full example. t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, @@ -137,6 +140,7 @@ func Example_unmetExpectation() { } func Example_unexpectedCall() { + // See ./testdata/example.txt for a full example. t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, @@ -165,6 +169,7 @@ func Example_unexpectedCall() { } func Example_allowRepeatedCalls() { + // See ./testdata/example.txt for a full example. t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectMany. var cache Cache = vermock.New(t, @@ -211,6 +216,7 @@ func Example_allowRepeatedCalls() { } func Example_orderedCalls() { + // See ./testdata/example.txt for a full example. t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectInOrder. var cache Cache = vermock.New(t, @@ -240,6 +246,7 @@ func Example_orderedCalls() { } func Example_mixedOrderedCalls() { + // See ./testdata/example.txt for a full example. t := &exampleT{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectInOrder. get := vermock.Expect[mockCache]("Get", func(key string) (any, bool) { diff --git a/go.sum b/go.sum index e7257f8..0a6f327 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3 golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= diff --git a/mod_test.go b/mod_test.go new file mode 100644 index 0000000..ca7bf1b --- /dev/null +++ b/mod_test.go @@ -0,0 +1,76 @@ +package vermock_test + +import ( + "bytes" + "context" + "flag" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + + "rsc.io/script" + "rsc.io/script/scripttest" +) + +var env []string + +func TestModules(t *testing.T) { + ctx, eng := context.Background(), script.NewEngine() + scripttest.Test(t, ctx, eng, env, "testdata/*.txt") +} + +func TestMain(m *testing.M) { + // Setup environment for scripttest. + env = []string{ + "HOME=" + os.Getenv("HOME"), + } + + // The Module Under Test (MUT) directory. + mutdir, err := os.Getwd() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + env = append(env, "MUT="+mutdir) + + // When running with -test.gocoverdir, forward this setting to each + // test script. + fset := flag.NewFlagSet("vermockgen", flag.ContinueOnError) + fset.SetOutput(&bytes.Buffer{}) // ignore errors + covdir := fset.String("test.gocoverdir", "", "write coverage intermediate files to this directory") + err = fset.Parse(os.Args[1:]) + for err != nil { + err = fset.Parse(fset.Args()) + } + + if *covdir != "" { + env = append(env, "GOCOVERDIR="+*covdir) + } + + // Temporary directory for vermockgen binary. + bindir, err := os.MkdirTemp("", "vermockgen") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer os.RemoveAll(bindir) + args := []string{"build"} + if *covdir != "" { + args = append(args, "-cover") + } + args = append(args, "-o", filepath.Join(bindir, "vermockgen"), "./cmd/vermockgen") + cmd := exec.Command("go", args...) + cmd.Env = env + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + env = append(env, "PATH="+strings.Join([]string{bindir, os.Getenv("PATH")}, ":")) + + m.Run() +} diff --git a/testdata/example.txt b/testdata/example.txt new file mode 100644 index 0000000..941443f --- /dev/null +++ b/testdata/example.txt @@ -0,0 +1,285 @@ +# Complete example usage of vermockgen. +# +# For a description of this format see https://pkg.go.dev/golang.org/x/tools/txtar and https://pkg.go.dev/rsc.io/script@v0.0.1#hdr-Script_Language. + +# Setup module. +exec go mod edit -replace github.com/Versent/go-vermock=$MUT +exec go mod tidy + +# Run vermockgen. +exec vermockgen + +# Run go test and strip out elapsed time and coverage data. +exec bash -c 'go test -v ${GOCOVERDIR:+-coverpkg=github.com/Versent/go-vermock/... -test.gocoverdir=$GOCOVERDIR} | sed "/\\scoverage:\\s/d;s/\\s*\\(([0-9.]\\+s)\\|\t[0-9.]\\+s\\)$//"' + +# Compare with expected output +cmpenv stdout testdata/stdout +cmpenv stderr testdata/stderr + +-- go.mod -- +module example.com + +go 1.20 +-- example.go -- +package example + +// Cache contains a variety of methods with different signatures. +type Cache interface { + Put(string, any) error + Get(string) (any, bool) + Delete(string) + Load(...string) +} +-- mock_test.go -- +//go:build vermockstub + +package example_test + +import ( + eg "example.com" +) + +type mockCache struct { + eg.Cache +} + +// UnusedCache is useful to show that a test's intent is that none of the +// interface methods are called. +var UnusedCache func(*mockCache) = nil +-- example_test.go -- +// To avoid problems when generating vermockgen code after the tests are +// defined, use buildtags to hide this file from the generator. +// Alternatively, just ensure the vermockgen code is generated before writing +// your tests (and don't forget to commit it to your SCM system). +//go:build !vermockstub + +package example_test + +import ( + "fmt" + "testing" + + vermock "github.com/Versent/go-vermock" + + eg "example.com" +) + +func TestUnusedCache(t *testing.T) { + // 1. Create a mock object. + var cache eg.Cache = vermock.New(t, UnusedCache) + // 2. Use the mock object in your code under test. + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestPass(t *testing.T) { + // 1. Create a mock object with expected calls. + var cache eg.Cache = vermock.New(t, + // delegate function can receive testing.TB + vermock.Expect[mockCache]("Get", func(t testing.TB, key string) (any, bool) { + return "bar", true + }), + vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { + return nil + }), + // or only the method arguments + vermock.Expect[mockCache]("Delete", func(key string) {}), + // you may prefer to define a helper function + ExpectDelete(func(t testing.TB, key string) {}), + ) + // 2. Use the mock object in your code under test. + cache.Put("foo", "bar") + cache.Get("foo") + cache.Delete("foo") + cache.Delete("foo") + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestUnmetExpectation(t *testing.T) { + // 1. Create a mock object with expected calls. + var cache eg.Cache = vermock.New(t, + // delegate function can receive testing.TB + vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { + fmt.Println("put", key, value) + return nil + }), + // or *testing.T + vermock.Expect[mockCache]("Get", func(t *testing.T, key string) (any, bool) { + fmt.Println("get", key) + return "bar", true + }), + // or only the method arguments + vermock.Expect[mockCache]("Delete", func(key string) { + fmt.Println("delete", key) + }), + // you may prefer to define a helper function + ExpectDelete(func(t testing.TB, key string) { + t.Log("this is not going to be called; causing t.Fail() to be called by vermock.AssertExpectedCalls") + }), + ) + // 2. Use the mock object in your code under test. + cache.Put("foo", "bar") + cache.Get("foo") + cache.Delete("foo") + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestUnexpectedCall(t *testing.T) { + // 1. Create a mock object with expected calls. + var cache eg.Cache = vermock.New(t, + // delegate function can receive testing.TB + vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { + fmt.Println("put", key, value) + return nil + }), + // or only the method arguments + vermock.Expect[mockCache]("Delete", func(key string) { + fmt.Println("delete", key) + }), + ) + // 2. Use the mock object in your code under test. + cache.Put("foo", "bar") + cache.Get("foo") + cache.Delete("foo") + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestAllowRepeatedCalls(t *testing.T) { + // 1. Create a mock object with ExpectMany. + var cache eg.Cache = vermock.New(t, + // delegate function may receive a call counter and the method arguments + vermock.ExpectMany[mockCache]("Load", func(n vermock.CallCount, keys ...string) { + fmt.Println("load", n, keys) + }), + // and testing.TB + vermock.ExpectMany[mockCache]("Load", func(t testing.TB, n vermock.CallCount, keys ...string) { + fmt.Println("load", n, keys) + }), + // or *testing.T + vermock.ExpectMany[mockCache]("Load", func(t *testing.T, n vermock.CallCount, keys ...string) { + fmt.Println("load", n, keys) + }), + // or only testing.TB/*testing.T + vermock.ExpectMany[mockCache]("Load", func(t testing.TB, keys ...string) { + fmt.Println("load 3", keys) + }), + // or only the method arguments + vermock.ExpectMany[mockCache]("Load", func(keys ...string) { + fmt.Println("load 4", keys) + }), + ) + // 2. Use the mock object in your code under test. + cache.Load("foo", "bar") + cache.Load("baz") + cache.Load("foo") + cache.Load("bar") + cache.Load("baz") + cache.Load("foo", "bar", "baz") + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestOrderedCalls(t *testing.T) { + // 1. Create a mock object with ExpectInOrder. + var cache eg.Cache = vermock.New(t, + vermock.ExpectInOrder( + vermock.Expect[mockCache]("Put", func(key string, value any) error { + fmt.Println("put", key, value) + return nil + }), + vermock.Expect[mockCache]("Get", func(key string) (any, bool) { + fmt.Println("get", key) + return "bar", true + }), + ), + ) + // 2. Use the mock object in your code under test. + cache.Get("foo") + cache.Put("foo", "bar") + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} + +func TestMixedOrderedCalls(t *testing.T) { + // 1. Create a mock object with ExpectInOrder. + get := vermock.Expect[mockCache]("Get", func(key string) (any, bool) { + return "bar", true + }) + put := vermock.Expect[mockCache]("Put", func(key string, value any) error { + return nil + }) + var cache eg.Cache = vermock.New(t, + get, put, + vermock.ExpectInOrder(put, get), + get, put, + ) + // 2. Use the mock object in your code under test. + for i := 0; i < 3; i++ { + cache.Put(fmt.Sprint("foo", i), "bar") + cache.Get(fmt.Sprint("foo", i)) + } + // 3. Assert that all expected methods were called. + vermock.AssertExpectedCalls(t, cache) +} +-- testdata/stderr -- +-- testdata/stdout -- +=== RUN TestUnusedCache +--- PASS: TestUnusedCache +=== RUN TestPass + vermock_gen_test.go:65: call to Put: 0/0 + vermock_gen_test.go:41: call to Get: 0/0 + vermock_gen_test.go:29: call to Delete: 0/0 + vermock_gen_test.go:29: call to Delete: 1/0 +--- PASS: TestPass +=== RUN TestUnmetExpectation + vermock_gen_test.go:65: call to Put: 0/0 +put foo bar + vermock_gen_test.go:41: call to Get: 0/0 +get foo + vermock_gen_test.go:29: call to Delete: 0/0 +delete foo + example_test.go:77: failed to make call to Delete: only got one call +--- FAIL: TestUnmetExpectation +=== RUN TestUnexpectedCall + vermock_gen_test.go:65: call to Put: 0/0 +put foo bar + vermock_gen_test.go:41: unexpected call to Get + vermock_gen_test.go:29: call to Delete: 0/0 +delete foo +--- FAIL: TestUnexpectedCall +=== RUN TestAllowRepeatedCalls + vermock_gen_test.go:53: call to Load: 0/0 +load 0 [foo bar] + vermock_gen_test.go:53: call to Load: 1/0 +load 1 [baz] + vermock_gen_test.go:53: call to Load: 2/0 +load 2 [foo] + vermock_gen_test.go:53: call to Load: 3/0 +load 3 [bar] + vermock_gen_test.go:53: call to Load: 4/0 +load 4 [baz] + vermock_gen_test.go:53: call to Load: 5/0 +load 4 [foo bar baz] +--- PASS: TestAllowRepeatedCalls +=== RUN TestOrderedCalls + vermock_gen_test.go:41: out of order call to Get: expected 2, got 1 + vermock_gen_test.go:41: call to Get: 0/1 +get foo + vermock_gen_test.go:65: out of order call to Put: expected 1, got 2 + vermock_gen_test.go:65: call to Put: 0/2 +put foo bar +--- FAIL: TestOrderedCalls +=== RUN TestMixedOrderedCalls + vermock_gen_test.go:65: call to Put: 0/0 + vermock_gen_test.go:41: call to Get: 0/0 + vermock_gen_test.go:65: call to Put: 1/1 + vermock_gen_test.go:41: call to Get: 1/2 + vermock_gen_test.go:65: call to Put: 2/2 + vermock_gen_test.go:41: call to Get: 2/2 +--- PASS: TestMixedOrderedCalls +FAIL +exit status 1 +FAIL example.com From 2971f7bf859a0bfd7a7ae879fbcc5dadb1019f79 Mon Sep 17 00:00:00 2001 From: Corin Lawson Date: Fri, 22 Mar 2024 20:21:26 +1100 Subject: [PATCH 2/4] refactor: remove sed dependency Prior to this change, sed was used to remove the coverage results and timing data from test output of the test cases (i.e. where a test invoked `go test` via rsc.io/script). This is important because the test not reproducible otherwise. However, complex regular expressions to do this is fragile and difficult to change. This change wraps the go test command in a custom rsc.io/script command; this allows us to filter the JSON formatted test output using a go function. Only the output relating to individual tests is outputed (i.e. summary information is excluded) and we generate our own result (i.e. pass/fail/skip) lines with the elapsed time removed. Also, we now automatically pass the correct -coverpkg and -test.gocoverdir arguments without the conditional bash variable expansion polluting every txt archive file. --- cmd/vermockgen/main_test.go | 3 +- mod_test.go | 95 ++++++++++++++++++++++++++++++++++++- testdata/example.txt | 4 +- 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/cmd/vermockgen/main_test.go b/cmd/vermockgen/main_test.go index 3b23923..db25a53 100644 --- a/cmd/vermockgen/main_test.go +++ b/cmd/vermockgen/main_test.go @@ -16,6 +16,7 @@ import ( ) var env []string +var covdir *string func TestMockgen(t *testing.T) { ctx, eng := context.Background(), script.NewEngine() @@ -43,7 +44,7 @@ func TestMain(m *testing.M) { // test script. fset := flag.NewFlagSet("vermockgen", flag.ContinueOnError) fset.SetOutput(&bytes.Buffer{}) // ignore errors - covdir := fset.String("test.gocoverdir", "", "write coverage intermediate files to this directory") + covdir = fset.String("test.gocoverdir", "", "write coverage intermediate files to this directory") err = fset.Parse(os.Args[1:]) for err != nil { err = fset.Parse(fset.Args()) diff --git a/mod_test.go b/mod_test.go index ca7bf1b..fd7ac04 100644 --- a/mod_test.go +++ b/mod_test.go @@ -3,6 +3,8 @@ package vermock_test import ( "bytes" "context" + "encoding/json" + "errors" "flag" "fmt" "os" @@ -10,15 +12,18 @@ import ( "path/filepath" "strings" "testing" + "time" "rsc.io/script" "rsc.io/script/scripttest" ) var env []string +var covdir *string func TestModules(t *testing.T) { ctx, eng := context.Background(), script.NewEngine() + eng.Cmds["go-test"] = GoTestCommand(*covdir) scripttest.Test(t, ctx, eng, env, "testdata/*.txt") } @@ -40,7 +45,7 @@ func TestMain(m *testing.M) { // test script. fset := flag.NewFlagSet("vermockgen", flag.ContinueOnError) fset.SetOutput(&bytes.Buffer{}) // ignore errors - covdir := fset.String("test.gocoverdir", "", "write coverage intermediate files to this directory") + covdir = fset.String("test.gocoverdir", "", "write coverage intermediate files to this directory") err = fset.Parse(os.Args[1:]) for err != nil { err = fset.Parse(fset.Args()) @@ -74,3 +79,91 @@ func TestMain(m *testing.M) { m.Run() } + +type goTestCmd struct { + covdir string +} + +func GoTestCommand(covdir string) *goTestCmd { + return &goTestCmd{covdir: covdir} +} + +func (*goTestCmd) Usage() *script.CmdUsage { + return &script.CmdUsage{ + Summary: "wrapper for the go test command", + Args: "go-test [build/test flags] [packages] [build/test flags & test binary flags]", + Detail: []string{ + `The standard go test command output includes data about elapsed time and code `, + `coverage. This can be a hinderance when comparing the output of two test runs. `, + `This wrapper will strip out all the non-reproducible data from the output. It `, + `also automatically sets the -coverpkg and -test.gocoverdir flags if the `, + `GOCOVERDIR environment variable is set.`, + }, + } +} + +func (cmd *goTestCmd) Run(s *script.State, args ...string) (script.WaitFunc, error) { + var buf, stderr bytes.Buffer + goargs := []string{"test", "-json"} + if cmd.covdir != "" { + goargs = append( + goargs, + "-coverpkg=github.com/Versent/go-vermock/...", + "-test.gocoverdir="+cmd.covdir, + ) + } + goargs = append(goargs, args...) + gocmd := exec.CommandContext(s.Context(), "go", goargs...) + gocmd.Dir = s.Getwd() + gocmd.Env = s.Environ() + gocmd.Stdout = &buf + gocmd.Stderr = &stderr + err := gocmd.Start() + + return func(s *script.State) (_, _ string, err error) { + err = gocmd.Wait() + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + err = nil + } + if err != nil { + println(stderr.String(), err.Error()) + return "", stderr.String(), err + } + + var stdout strings.Builder + decoder := json.NewDecoder(&buf) + + for decoder.More() { + var event struct { + Time time.Time + Action string + Package string + Test string + Elapsed float64 + Output string + } + if err := decoder.Decode(&event); err != nil { + return "", stderr.String(), err + } + if event.Test == "" { + continue + } + switch event.Action { + case "start", "run", "pause", "cont", "bench": + continue + case "output": + if strings.HasPrefix(strings.TrimSpace(event.Output), "--- ") { + continue + } + stdout.WriteString(event.Output) + case "pass", "fail", "skip": + fmt.Fprintf(&stdout, "--- %s: %s\n", strings.ToUpper(event.Action), event.Test) + } + } + if exitErr != nil { + fmt.Fprintln(&stdout, exitErr.Error()) + } + return stdout.String(), stderr.String(), err + }, err +} diff --git a/testdata/example.txt b/testdata/example.txt index 941443f..93a58cb 100644 --- a/testdata/example.txt +++ b/testdata/example.txt @@ -10,7 +10,7 @@ exec go mod tidy exec vermockgen # Run go test and strip out elapsed time and coverage data. -exec bash -c 'go test -v ${GOCOVERDIR:+-coverpkg=github.com/Versent/go-vermock/... -test.gocoverdir=$GOCOVERDIR} | sed "/\\scoverage:\\s/d;s/\\s*\\(([0-9.]\\+s)\\|\t[0-9.]\\+s\\)$//"' +go-test -v # Compare with expected output cmpenv stdout testdata/stdout @@ -280,6 +280,4 @@ put foo bar vermock_gen_test.go:65: call to Put: 2/2 vermock_gen_test.go:41: call to Get: 2/2 --- PASS: TestMixedOrderedCalls -FAIL exit status 1 -FAIL example.com From 81a63ae99229613e613168c2cf652363f4c1c546 Mon Sep 17 00:00:00 2001 From: Corin Lawson Date: Fri, 22 Mar 2024 20:35:11 +1100 Subject: [PATCH 3/4] chore: update to go 1.21 Prior to this change, we using go 1.20. This change updates to go 1.21 and introduces the toolchain directive. With this update the tools.go file is no longer required for the test cases and it also highlighted some missing go mod tidy commands in the test cases. --- cmd/vermockgen/testdata/commands.txt | 6 ------ cmd/vermockgen/testdata/fallback.txt | 6 ------ cmd/vermockgen/testdata/fallback_all_args.txt | 6 ------ cmd/vermockgen/testdata/fallback_flag_undefined.txt | 6 ------ cmd/vermockgen/testdata/fallback_header.txt | 6 ------ cmd/vermockgen/testdata/fallback_packages_missing.txt | 6 ------ cmd/vermockgen/testdata/fallback_tags.txt | 6 ------ cmd/vermockgen/testdata/flags.txt | 6 ------ cmd/vermockgen/testdata/flags_gen.txt | 6 ------ cmd/vermockgen/testdata/gen.txt | 6 ------ cmd/vermockgen/testdata/gen_all_args.txt | 6 ------ cmd/vermockgen/testdata/gen_flag_undefined.txt | 6 ------ cmd/vermockgen/testdata/gen_header.txt | 6 ------ cmd/vermockgen/testdata/gen_package.txt | 6 ------ cmd/vermockgen/testdata/gen_tags.txt | 6 ------ go.mod | 4 +++- internal/mock/generate_test.go | 6 +++++- internal/mock/testdata/custom_func.txt | 2 ++ internal/mock/testdata/custom_func_multi_expect.txt | 2 ++ internal/mock/testdata/custom_func_multi_file.txt | 2 ++ 20 files changed, 14 insertions(+), 92 deletions(-) diff --git a/cmd/vermockgen/testdata/commands.txt b/cmd/vermockgen/testdata/commands.txt index e60a04b..fc7c2eb 100644 --- a/cmd/vermockgen/testdata/commands.txt +++ b/cmd/vermockgen/testdata/commands.txt @@ -17,9 +17,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/fallback.txt b/cmd/vermockgen/testdata/fallback.txt index 3b4062a..6b4cd2a 100644 --- a/cmd/vermockgen/testdata/fallback.txt +++ b/cmd/vermockgen/testdata/fallback.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- mock.go -- //go:build vermockstub diff --git a/cmd/vermockgen/testdata/fallback_all_args.txt b/cmd/vermockgen/testdata/fallback_all_args.txt index 79012fc..1245fbe 100644 --- a/cmd/vermockgen/testdata/fallback_all_args.txt +++ b/cmd/vermockgen/testdata/fallback_all_args.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- HEADER -- // HEADER -- mock.go -- diff --git a/cmd/vermockgen/testdata/fallback_flag_undefined.txt b/cmd/vermockgen/testdata/fallback_flag_undefined.txt index c3f19ae..c09244e 100644 --- a/cmd/vermockgen/testdata/fallback_flag_undefined.txt +++ b/cmd/vermockgen/testdata/fallback_flag_undefined.txt @@ -24,9 +24,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/fallback_header.txt b/cmd/vermockgen/testdata/fallback_header.txt index e9a6ed6..7f2f23c 100644 --- a/cmd/vermockgen/testdata/fallback_header.txt +++ b/cmd/vermockgen/testdata/fallback_header.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- HEADER -- // HEADER -- mock.go -- diff --git a/cmd/vermockgen/testdata/fallback_packages_missing.txt b/cmd/vermockgen/testdata/fallback_packages_missing.txt index 58a017f..fe79a01 100644 --- a/cmd/vermockgen/testdata/fallback_packages_missing.txt +++ b/cmd/vermockgen/testdata/fallback_packages_missing.txt @@ -15,9 +15,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/fallback_tags.txt b/cmd/vermockgen/testdata/fallback_tags.txt index 0955f63..e1b2b61 100644 --- a/cmd/vermockgen/testdata/fallback_tags.txt +++ b/cmd/vermockgen/testdata/fallback_tags.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- mock.go -- //go:build vermockstub diff --git a/cmd/vermockgen/testdata/flags.txt b/cmd/vermockgen/testdata/flags.txt index 559e65d..58b8236 100644 --- a/cmd/vermockgen/testdata/flags.txt +++ b/cmd/vermockgen/testdata/flags.txt @@ -13,9 +13,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/flags_gen.txt b/cmd/vermockgen/testdata/flags_gen.txt index 2924c8c..977dd82 100644 --- a/cmd/vermockgen/testdata/flags_gen.txt +++ b/cmd/vermockgen/testdata/flags_gen.txt @@ -17,9 +17,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/gen.txt b/cmd/vermockgen/testdata/gen.txt index 3a2dd57..f43479d 100644 --- a/cmd/vermockgen/testdata/gen.txt +++ b/cmd/vermockgen/testdata/gen.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- mock.go -- //go:build vermockstub diff --git a/cmd/vermockgen/testdata/gen_all_args.txt b/cmd/vermockgen/testdata/gen_all_args.txt index a69ea96..9b727cf 100644 --- a/cmd/vermockgen/testdata/gen_all_args.txt +++ b/cmd/vermockgen/testdata/gen_all_args.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- HEADER -- // HEADER -- mock.go -- diff --git a/cmd/vermockgen/testdata/gen_flag_undefined.txt b/cmd/vermockgen/testdata/gen_flag_undefined.txt index 7140362..25844dc 100644 --- a/cmd/vermockgen/testdata/gen_flag_undefined.txt +++ b/cmd/vermockgen/testdata/gen_flag_undefined.txt @@ -24,9 +24,3 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) diff --git a/cmd/vermockgen/testdata/gen_header.txt b/cmd/vermockgen/testdata/gen_header.txt index d953aac..f52b44f 100644 --- a/cmd/vermockgen/testdata/gen_header.txt +++ b/cmd/vermockgen/testdata/gen_header.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- HEADER -- // HEADER -- mock.go -- diff --git a/cmd/vermockgen/testdata/gen_package.txt b/cmd/vermockgen/testdata/gen_package.txt index 81cdf0c..788f5f8 100644 --- a/cmd/vermockgen/testdata/gen_package.txt +++ b/cmd/vermockgen/testdata/gen_package.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- mock.go -- //go:build vermockstub diff --git a/cmd/vermockgen/testdata/gen_tags.txt b/cmd/vermockgen/testdata/gen_tags.txt index 07c934b..ada93f2 100644 --- a/cmd/vermockgen/testdata/gen_tags.txt +++ b/cmd/vermockgen/testdata/gen_tags.txt @@ -14,12 +14,6 @@ module test go 1.20 require github.com/Versent/go-vermock v0.0.0-00010101000000-000000000000 --- tools.go -- -package main - -import ( - _ "github.com/Versent/go-vermock/cmd/vermockgen" -) -- mock.go -- //go:build vermockstub diff --git a/go.mod b/go.mod index db856e7..1ad6ccd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/Versent/go-vermock -go 1.20 +go 1.21 + +toolchain go1.21.6 require ( github.com/google/subcommands v1.2.0 diff --git a/internal/mock/generate_test.go b/internal/mock/generate_test.go index 4afffb5..be79fdf 100644 --- a/internal/mock/generate_test.go +++ b/internal/mock/generate_test.go @@ -30,7 +30,11 @@ func TestGenerate(t *testing.T) { t, context.Background(), engine, - []string{"MUT=" + mutdir}, + []string{ + "PATH=" + os.Getenv("PATH"), + "HOME=" + os.Getenv("HOME"), + "MUT=" + mutdir, + }, "testdata/*.txt", ) } diff --git a/internal/mock/testdata/custom_func.txt b/internal/mock/testdata/custom_func.txt index a1b333f..f843a80 100644 --- a/internal/mock/testdata/custom_func.txt +++ b/internal/mock/testdata/custom_func.txt @@ -3,6 +3,8 @@ replace ../../../.. $MUT go.mod +exec go mod tidy + vermockgen cmpenv stdout testdata/stdout diff --git a/internal/mock/testdata/custom_func_multi_expect.txt b/internal/mock/testdata/custom_func_multi_expect.txt index dcdfef4..f0c2677 100644 --- a/internal/mock/testdata/custom_func_multi_expect.txt +++ b/internal/mock/testdata/custom_func_multi_expect.txt @@ -3,6 +3,8 @@ replace ../../../.. $MUT go.mod +exec go mod tidy + vermockgen cmpenv stdout testdata/stdout diff --git a/internal/mock/testdata/custom_func_multi_file.txt b/internal/mock/testdata/custom_func_multi_file.txt index 42ed53c..4b6edf6 100644 --- a/internal/mock/testdata/custom_func_multi_file.txt +++ b/internal/mock/testdata/custom_func_multi_file.txt @@ -3,6 +3,8 @@ replace ../../../.. $MUT go.mod +exec go mod tidy + vermockgen cmpenv stdout testdata/stdout From ac9ea6898982a832a354ceb172a7e8df661e0245 Mon Sep 17 00:00:00 2001 From: Corin Lawson Date: Fri, 22 Mar 2024 20:43:24 +1100 Subject: [PATCH 4/4] test: introduce basic tests for i/cmd/vermockgen Prior to this change, there were no test files for the package: github.com/Versent/go-vermock/internal/cmd/vermockgen. This change introduces limited tests for SetFlags and Execute methods. --- internal/cmd/vermockgen/gen_test.go | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 internal/cmd/vermockgen/gen_test.go diff --git a/internal/cmd/vermockgen/gen_test.go b/internal/cmd/vermockgen/gen_test.go new file mode 100644 index 0000000..4e00c93 --- /dev/null +++ b/internal/cmd/vermockgen/gen_test.go @@ -0,0 +1,36 @@ +package vermockgen_test + +import ( + "bytes" + "flag" + "log" + "testing" + + vermockgen "github.com/Versent/go-vermock/internal/cmd/vermockgen" +) + +func TestSetFlags(t *testing.T) { + f := flag.NewFlagSet("vermockgen", flag.ContinueOnError) + vermockgen.NewGenCmd(nil, f) + expected := []string{"header", "tags"} + f.VisitAll(func(f *flag.Flag) { + if len(expected) == 0 { + t.Errorf("unexpected flag %q", f.Name) + return + } + + var got, want string + got, want, expected = f.Name, expected[0], expected[1:] + if got != want { + t.Errorf("unexpected name, got %q, want %q", got, want) + } + }) +} + +func TestExecute(t *testing.T) { + var buf bytes.Buffer + l := log.New(&buf, "", 0) + f := flag.NewFlagSet("vermockgen", flag.ContinueOnError) + vermockgen.NewGenCmd(l, f) + +}