Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to create a clio.Application that runs test assertions instead of cmd.RunE #37

Merged
merged 8 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions cliotestutils/application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cliotestutils

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"

"github.com/anchore/clio"
)

// NewApplication takes a testing.T, a clio setup config, and a slice of assertions, and returns
// a clio application that will, instead of setting up commands with their normal RunE, set up commands
// such that the assertions are called with the testing.T after config state is set up by reading flags,
// env vars, and config files. Useful for testing that expected configuration options are wired up.
// Note that initializers will be cleared from the clio setup config, since the initialization may happen
// more than once and affect global state. For necessary global state, a workaround is to set it in a TestingMain.
func NewApplication(t *testing.T, cfg *clio.SetupConfig, assertions ...AssertionFunc) clio.Application {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the composition approach here - it might get tough to debug this, since the assertions can happen so far away from the thing they are asserting against, but I think that's a second order concern.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

cfg.Initializers = nil
wagoodman marked this conversation as resolved.
Show resolved Hide resolved
a := clio.New(*cfg)

var asserter assertionClosure = func(cmd *cobra.Command, args []string, cfgs ...any) {
for _, assertion := range assertions {
assertion(t, cmd, args, cfgs...)
}
}

return &testApplication{
a,
asserter,
}
}

type AssertionFunc func(t *testing.T, cmd *cobra.Command, args []string, cfgs ...any)

func OptionsEquals(wantOpts any) AssertionFunc {
return func(t *testing.T, cmd *cobra.Command, args []string, cfgs ...any) {
assert.Equal(t, len(cfgs), 1)
if d := cmp.Diff(wantOpts, cfgs[0]); d != "" {
t.Errorf("mismatched options (-want +got):\n%s", d)
}
}
}

type assertionClosure func(cmd *cobra.Command, args []string, cfgs ...any)

type testApplication struct {
clio.Application
assertion assertionClosure
}

func (a *testApplication) SetupCommand(cmd *cobra.Command, cfgs ...any) *cobra.Command {
cmd.RunE = func(cmd *cobra.Command, args []string) error {
a.assertion(cmd, args, cfgs...)
return nil
}
return a.Application.SetupCommand(cmd, cfgs...)
}

func (a *testApplication) SetupRootCommand(cmd *cobra.Command, cfgs ...any) *cobra.Command {
cmd.RunE = func(cmd *cobra.Command, args []string) error {
a.assertion(cmd, args, cfgs...)
return nil
}
return a.Application.SetupRootCommand(cmd, cfgs...)
}

/*
// TODO: WISHLIST:
1. Helper to wire up a test fixture as the only config file that will be found
2. Set env vars by passing map[string]string (currently possible by caller in test; a helper here would be nice.)
*/
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.18
require (
github.com/anchore/fangs v0.0.0-20230807173929-13c94c86f47e
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
github.com/google/go-cmp v0.5.9
github.com/gookit/color v1.5.4
github.com/iancoleman/strcase v0.3.0
github.com/pborman/indent v1.2.1
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
Expand Down
Loading