feat: refactor test helpers
Better organize and allow for re-use across packages. Signed-off-by: Brian McGee <brian@bmcgee.ie>
This commit is contained in:
parent
256c6774c6
commit
56cf0cf979
|
@ -1,105 +1,21 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.numtide.com/numtide/treefmt/internal/test"
|
||||
|
||||
"git.numtide.com/numtide/treefmt/internal/format"
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/alecthomas/kong"
|
||||
cp "github.com/otiai10/copy"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func writeConfig(t *testing.T, path string, cfg format.Config) {
|
||||
t.Helper()
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create a new config file: %v", err)
|
||||
}
|
||||
encoder := toml.NewEncoder(f)
|
||||
if err = encoder.Encode(cfg); err != nil {
|
||||
t.Fatalf("failed to write to config file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newKong(t *testing.T, cli interface{}, options ...kong.Option) *kong.Kong {
|
||||
t.Helper()
|
||||
options = append([]kong.Option{
|
||||
kong.Name("test"),
|
||||
kong.Exit(func(int) {
|
||||
t.Helper()
|
||||
t.Fatalf("unexpected exit()")
|
||||
}),
|
||||
}, options...)
|
||||
parser, err := kong.New(cli, options...)
|
||||
assert.NoError(t, err)
|
||||
return parser
|
||||
}
|
||||
|
||||
func tempFile(t *testing.T, path string) *os.File {
|
||||
t.Helper()
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temporary file: %v", err)
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
func cmd(t *testing.T, args ...string) ([]byte, error) {
|
||||
t.Helper()
|
||||
|
||||
// create a new kong context
|
||||
p := newKong(t, &Cli)
|
||||
ctx, err := p.Parse(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tempDir := t.TempDir()
|
||||
tempOut := tempFile(t, filepath.Join(tempDir, "combined_output"))
|
||||
|
||||
// capture standard outputs before swapping them
|
||||
stdout := os.Stdout
|
||||
stderr := os.Stderr
|
||||
|
||||
// swap them temporarily
|
||||
os.Stdout = tempOut
|
||||
os.Stderr = tempOut
|
||||
|
||||
// run the command
|
||||
if err = ctx.Run(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// reset and read the temporary output
|
||||
if _, err = tempOut.Seek(0, 0); err != nil {
|
||||
return nil, fmt.Errorf("%w: failed to reset temp output for reading", err)
|
||||
}
|
||||
|
||||
out, err := io.ReadAll(tempOut)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: failed to read temp output", err)
|
||||
}
|
||||
|
||||
// swap outputs back
|
||||
os.Stdout = stdout
|
||||
os.Stderr = stderr
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func TestAllowMissingFormatter(t *testing.T) {
|
||||
as := require.New(t)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
configPath := tempDir + "/treefmt.toml"
|
||||
|
||||
writeConfig(t, configPath, format.Config{
|
||||
test.WriteConfig(t, configPath, format.Config{
|
||||
Formatters: map[string]*format.Formatter{
|
||||
"foo-fmt": {
|
||||
Command: "foo-fmt",
|
||||
|
@ -117,12 +33,10 @@ func TestAllowMissingFormatter(t *testing.T) {
|
|||
func TestSpecifyingFormatters(t *testing.T) {
|
||||
as := require.New(t)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
tempDir := test.TempExamples(t)
|
||||
configPath := tempDir + "/treefmt.toml"
|
||||
|
||||
as.NoError(cp.Copy("../../test/examples", tempDir), "failed to copy test data to temp dir")
|
||||
|
||||
writeConfig(t, configPath, format.Config{
|
||||
test.WriteConfig(t, configPath, format.Config{
|
||||
Formatters: map[string]*format.Formatter{
|
||||
"elm": {
|
||||
Command: "echo",
|
||||
|
|
70
internal/cli/helpers_test.go
Normal file
70
internal/cli/helpers_test.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.numtide.com/numtide/treefmt/internal/test"
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newKong(t *testing.T, cli interface{}, options ...kong.Option) *kong.Kong {
|
||||
t.Helper()
|
||||
options = append([]kong.Option{
|
||||
kong.Name("test"),
|
||||
kong.Exit(func(int) {
|
||||
t.Helper()
|
||||
t.Fatalf("unexpected exit()")
|
||||
}),
|
||||
}, options...)
|
||||
parser, err := kong.New(cli, options...)
|
||||
require.NoError(t, err)
|
||||
return parser
|
||||
}
|
||||
|
||||
func cmd(t *testing.T, args ...string) ([]byte, error) {
|
||||
t.Helper()
|
||||
|
||||
// create a new kong context
|
||||
p := newKong(t, &Cli)
|
||||
ctx, err := p.Parse(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tempDir := t.TempDir()
|
||||
tempOut := test.TempFile(t, filepath.Join(tempDir, "combined_output"))
|
||||
|
||||
// capture standard outputs before swapping them
|
||||
stdout := os.Stdout
|
||||
stderr := os.Stderr
|
||||
|
||||
// swap them temporarily
|
||||
os.Stdout = tempOut
|
||||
os.Stderr = tempOut
|
||||
|
||||
// run the command
|
||||
if err = ctx.Run(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// reset and read the temporary output
|
||||
if _, err = tempOut.Seek(0, 0); err != nil {
|
||||
return nil, fmt.Errorf("%w: failed to reset temp output for reading", err)
|
||||
}
|
||||
|
||||
out, err := io.ReadAll(tempOut)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: failed to read temp output", err)
|
||||
}
|
||||
|
||||
// swap outputs back
|
||||
os.Stdout = stdout
|
||||
os.Stderr = stderr
|
||||
|
||||
return out, nil
|
||||
}
|
38
internal/test/temp.go
Normal file
38
internal/test/temp.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.numtide.com/numtide/treefmt/internal/format"
|
||||
"github.com/BurntSushi/toml"
|
||||
cp "github.com/otiai10/copy"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func WriteConfig(t *testing.T, path string, cfg format.Config) {
|
||||
t.Helper()
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create a new config file: %v", err)
|
||||
}
|
||||
encoder := toml.NewEncoder(f)
|
||||
if err = encoder.Encode(cfg); err != nil {
|
||||
t.Fatalf("failed to write to config file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TempExamples(t *testing.T) string {
|
||||
tempDir := t.TempDir()
|
||||
require.NoError(t, cp.Copy("../../test/examples", tempDir), "failed to copy test data to temp dir")
|
||||
return tempDir
|
||||
}
|
||||
|
||||
func TempFile(t *testing.T, path string) *os.File {
|
||||
t.Helper()
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temporary file: %v", err)
|
||||
}
|
||||
return file
|
||||
}
|
Reference in New Issue
Block a user