From cc7ca69800be2a4afe7dc2f0f4cdc34e09ef0898 Mon Sep 17 00:00:00 2001 From: Erik Berkun-Drevnig Date: Wed, 1 Jun 2022 11:53:59 -0400 Subject: [PATCH] cleanup (#6) * Cleanup public API * Move alias * Test coverage * Rename --- formatting/formatters.go | 20 -------- formatting/io.go | 18 ++++++++ gold/assertions.go | 46 +++++++++++++++++++ gold/asserts.go | 35 -------------- gold/gold.go | 13 ++++-- gold/gold_test.go | 41 ++++++++++------- .../TestDiffGoldenFile/empty_json.golden.json | 3 ++ ...eq.golden.json => assert_json.golden.json} | 0 ...t_eq.golden.txt => assert_text.golden.txt} | 0 ...eq.golden.toml => assert_toml.golden.toml} | 0 ..._eq.golden.toml => assert_xml.golden.toml} | 0 ...eq.golden.yaml => assert_yaml.golden.yaml} | 0 .../TestInvalidData/valid_json.golden.json | 1 + 13 files changed, 101 insertions(+), 76 deletions(-) create mode 100644 formatting/io.go create mode 100644 gold/assertions.go delete mode 100644 gold/asserts.go create mode 100644 gold/testdata/TestDiffGoldenFile/empty_json.golden.json rename gold/testdata/TestExistingFiles/{json_eq.golden.json => assert_json.golden.json} (100%) rename gold/testdata/TestExistingFiles/{text_eq.golden.txt => assert_text.golden.txt} (100%) rename gold/testdata/TestExistingFiles/{toml_eq.golden.toml => assert_toml.golden.toml} (100%) rename gold/testdata/TestExistingFiles/{xml_eq.golden.toml => assert_xml.golden.toml} (100%) rename gold/testdata/TestExistingFiles/{yaml_eq.golden.yaml => assert_yaml.golden.yaml} (100%) create mode 100644 gold/testdata/TestInvalidData/valid_json.golden.json diff --git a/formatting/formatters.go b/formatting/formatters.go index fcabfb7..1385548 100644 --- a/formatting/formatters.go +++ b/formatting/formatters.go @@ -10,26 +10,6 @@ import ( "gopkg.in/yaml.v3" ) -// Formats is an alias for function signature that reads from reader, formats it and writes to writer. -type Formats func(reader io.Reader, writer io.Writer) error - -type encoder interface { - Encode(v interface{}) error -} - -type decoder interface { - Decode(v interface{}) error -} - -func format(encoder encoder, decoder decoder) error { - var decoded interface{} - err := decoder.Decode(&decoded) - if err != nil { - return err - } - return encoder.Encode(decoded) -} - // JSON formats the contents of reader and writes the results to writer. func JSON(reader io.Reader, writer io.Writer) error { decoder := json.NewDecoder(reader) diff --git a/formatting/io.go b/formatting/io.go new file mode 100644 index 0000000..82c59a9 --- /dev/null +++ b/formatting/io.go @@ -0,0 +1,18 @@ +package formatting + +type encoder interface { + Encode(v interface{}) error +} + +type decoder interface { + Decode(v interface{}) error +} + +func format(encoder encoder, decoder decoder) error { + var decoded interface{} + err := decoder.Decode(&decoded) + if err != nil { + return err + } + return encoder.Encode(decoded) +} diff --git a/gold/assertions.go b/gold/assertions.go new file mode 100644 index 0000000..685d88d --- /dev/null +++ b/gold/assertions.go @@ -0,0 +1,46 @@ +package gold + +import ( + "github.com/eberkund/rose/formatting" +) + +// AssertEqualsJSON compares a JSON string to the golden file. Data is +// noramlized before comparing so data which is formatted differently but +// semantically equivalent will not fail. +func (g *Gold) AssertEqualsJSON(goldenPath, actual string) { + g.t.Helper() + g.verify(g.assert(goldenPath, actual, formatting.JSON)) +} + +// AssertEqualsHTML compares an HTML string to the golden file. Data is +// noramlized before comparing so data which is formatted differently but +// semantically equivalent will not fail. +func (g *Gold) AssertEqualsHTML(goldenPath, actual string) { + g.t.Helper() + g.verify(g.assert(goldenPath, actual, formatting.HTML)) +} + +// AssertEqualsTOML compares a TOML string to the golden file. Data is +// noramlized before comparing so data which is formatted differently but +// semantically equivalent will not fail. +func (g *Gold) AssertEqualsTOML(goldenPath, actual string) { + g.t.Helper() + g.verify(g.assert(goldenPath, actual, formatting.TOML)) +} + +// AssertEqualsYAML compares a YAML string to the golden file. Data is +// noramlized before comparing so data which is formatted differently but +// semantically equivalent will not fail. +func (g *Gold) AssertEqualsYAML(goldenPath, actual string) { + g.t.Helper() + g.verify(g.assert(goldenPath, actual, formatting.YAML)) +} + +// AssertEquals compares a string to the contents of the golden file. If Gold +// was configured with an update flag which is true then the golden file will +// be created if it does not exist or overwritten with the supplied data if it +// does. +func (g *Gold) AssertEquals(goldenPath, actual string) { + g.t.Helper() + g.verify(g.assert(goldenPath, actual, formatting.NoOp)) +} diff --git a/gold/asserts.go b/gold/asserts.go deleted file mode 100644 index 0d7b3c1..0000000 --- a/gold/asserts.go +++ /dev/null @@ -1,35 +0,0 @@ -package gold - -import ( - "github.com/eberkund/rose/formatting" -) - -// JSONEq compares XML to golden file. -func (g *Gold) JSONEq(goldenPath, actual string) { - g.t.Helper() - g.verify(g.assert(goldenPath, actual, formatting.JSON)) -} - -// HTMLEq compares XML to golden file. -func (g *Gold) HTMLEq(goldenPath, actual string) { - g.t.Helper() - g.verify(g.assert(goldenPath, actual, formatting.HTML)) -} - -// TOMLEq compares TOML to golden file. -func (g *Gold) TOMLEq(goldenPath, actual string) { - g.t.Helper() - g.verify(g.assert(goldenPath, actual, formatting.TOML)) -} - -// YAMLEq compares YAML to golden file. -func (g *Gold) YAMLEq(goldenPath, actual string) { - g.t.Helper() - g.verify(g.assert(goldenPath, actual, formatting.YAML)) -} - -// Eq compares string to golden file. -func (g *Gold) Eq(goldenPath, actual string) { - g.t.Helper() - g.verify(g.assert(goldenPath, actual, formatting.NoOp)) -} diff --git a/gold/gold.go b/gold/gold.go index 3818475..328960a 100644 --- a/gold/gold.go +++ b/gold/gold.go @@ -2,16 +2,19 @@ package gold import ( "bytes" + "io" "os" "path/filepath" "strings" - "github.com/eberkund/rose/formatting" "github.com/pkg/errors" "github.com/pmezard/go-difflib/difflib" "github.com/spf13/afero" ) +// Formats is an alias for function signature that reads from reader, formats it and writes to writer. +type Formats func(reader io.Reader, writer io.Writer) error + // Testing is a subset of testing.TB that can be reimplemented. type Testing interface { Cleanup(func()) @@ -43,7 +46,7 @@ type Gold struct { fs afero.Fs } -// New initializes a Gold. +// New initializes an instance of Gold. func New(t Testing, options ...Option) *Gold { g := &Gold{ t: t, @@ -62,7 +65,7 @@ func (g *Gold) prependPrefix(path string) string { return filepath.Join(g.prefix, path) } -func (g *Gold) update(filename, actual string, formatter formatting.Formats) error { +func (g *Gold) update(filename, actual string, formatter Formats) error { if !g.flag { return nil } @@ -84,12 +87,12 @@ func (g *Gold) update(filename, actual string, formatter formatting.Formats) err } err = formatter(strings.NewReader(actual), file) if err != nil { - return errors.Wrap(err, "could not format or write inputData data to golden file") + return errors.Wrap(err, "could not format or write data to golden file") } return nil } -func (g *Gold) assert(goldenPath, given string, formatter formatting.Formats) (string, error) { +func (g *Gold) assert(goldenPath, given string, formatter Formats) (string, error) { prefixed := g.prependPrefix(goldenPath) if err := g.update(prefixed, given, formatter); err != nil { return "", err diff --git a/gold/gold_test.go b/gold/gold_test.go index 7f3b30d..3ba4a27 100644 --- a/gold/gold_test.go +++ b/gold/gold_test.go @@ -22,27 +22,27 @@ func TestExistingFiles(t *testing.T) { }{ "json": { inputData: `{"foo":123,"bar":"hello world","a":true}`, - goldenFile: "json_eq.golden.json", + goldenFile: "assert_json.golden.json", testFn: func(g *gold.Gold) func(string, string) { - return g.JSONEq + return g.AssertEqualsJSON }, }, "text": { - goldenFile: "text_eq.golden.txt", + goldenFile: "assert_text.golden.txt", inputData: "Hello\nWorld\n!", testFn: func(g *gold.Gold) func(string, string) { - return g.Eq + return g.AssertEquals }, }, "html": { - goldenFile: "xml_eq.golden.toml", + goldenFile: "assert_xml.golden.toml", inputData: ``, testFn: func(g *gold.Gold) func(string, string) { - return g.HTMLEq + return g.AssertEqualsHTML }, }, "toml": { - goldenFile: "toml_eq.golden.toml", + goldenFile: "assert_toml.golden.toml", inputData: ` Age = 25 Cats = [ "Cauchy", "Plato" ] @@ -52,11 +52,11 @@ Perfection = [ 6, 28, 496, 8128 ] DOB = 1987-07-05T05:45:00Z `, testFn: func(g *gold.Gold) func(string, string) { - return g.TOMLEq + return g.AssertEqualsTOML }, }, "yaml": { - goldenFile: "yaml_eq.golden.yaml", + goldenFile: "assert_yaml.golden.yaml", inputData: ` jobs: test: @@ -68,14 +68,14 @@ jobs: go-version: "1.18" `, testFn: func(g *gold.Gold) func(string, string) { - return g.YAMLEq + return g.AssertEqualsYAML }, }, } for name, tc := range testCases { - t.Run(name, func(subTest *testing.T) { + t.Run(name, func(st *testing.T) { g := gold.New( - subTest, + st, gold.WithPrefix("testdata", t.Name()), gold.WithFlag(*update), gold.WithFailAfter(), @@ -101,20 +101,29 @@ func TestUpdatingGoldenFile(t *testing.T) { require.NoError(t, err) g := gold.New(t, gold.WithFS(memFs), gold.WithFlag(true)) - g.Eq("test_data.txt", newData) + g.AssertEquals("test_data.txt", newData) data, err := afero.ReadFile(memFs, "testdata/test_data.txt") require.NoError(t, err) require.Equal(t, newData, string(data)) } +func TestInvalidData(t *testing.T) { + tm := mocks.NewTesting(t) + tm.On("Helper") + tm.On("Log", mock.Anything).Once() + tm.On("FailNow").Once() + g := gold.New(tm, gold.WithPrefix("testdata", t.Name())) + g.AssertEqualsJSON("empty_json.golden.json", "this is not valid JSON") +} + func TestDiffGoldenFile(t *testing.T) { tm := mocks.NewTesting(t) tm.On("Helper") tm.On("Logf", mock.Anything, mock.Anything).Once() tm.On("FailNow").Once() - g := gold.New(tm, gold.WithPrefix("testdata", "TestExistingFiles")) - g.JSONEq("json_eq.golden.json", "{}") + g := gold.New(tm, gold.WithPrefix("testdata", t.Name())) + g.AssertEqualsJSON("empty_json.golden.json", "{}") } func TestFileSystemError(t *testing.T) { @@ -124,5 +133,5 @@ func TestFileSystemError(t *testing.T) { tm.On("FailNow").Once() readOnlyFS := afero.NewReadOnlyFs(afero.NewMemMapFs()) g := gold.New(tm, gold.WithFS(readOnlyFS), gold.WithFlag(true)) - g.Eq("testdata/hello_world.txt", "Hello, World!") + g.AssertEquals("any/path/hello_world.golden.txt", "Hello, World!") } diff --git a/gold/testdata/TestDiffGoldenFile/empty_json.golden.json b/gold/testdata/TestDiffGoldenFile/empty_json.golden.json new file mode 100644 index 0000000..8a79687 --- /dev/null +++ b/gold/testdata/TestDiffGoldenFile/empty_json.golden.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/gold/testdata/TestExistingFiles/json_eq.golden.json b/gold/testdata/TestExistingFiles/assert_json.golden.json similarity index 100% rename from gold/testdata/TestExistingFiles/json_eq.golden.json rename to gold/testdata/TestExistingFiles/assert_json.golden.json diff --git a/gold/testdata/TestExistingFiles/text_eq.golden.txt b/gold/testdata/TestExistingFiles/assert_text.golden.txt similarity index 100% rename from gold/testdata/TestExistingFiles/text_eq.golden.txt rename to gold/testdata/TestExistingFiles/assert_text.golden.txt diff --git a/gold/testdata/TestExistingFiles/toml_eq.golden.toml b/gold/testdata/TestExistingFiles/assert_toml.golden.toml similarity index 100% rename from gold/testdata/TestExistingFiles/toml_eq.golden.toml rename to gold/testdata/TestExistingFiles/assert_toml.golden.toml diff --git a/gold/testdata/TestExistingFiles/xml_eq.golden.toml b/gold/testdata/TestExistingFiles/assert_xml.golden.toml similarity index 100% rename from gold/testdata/TestExistingFiles/xml_eq.golden.toml rename to gold/testdata/TestExistingFiles/assert_xml.golden.toml diff --git a/gold/testdata/TestExistingFiles/yaml_eq.golden.yaml b/gold/testdata/TestExistingFiles/assert_yaml.golden.yaml similarity index 100% rename from gold/testdata/TestExistingFiles/yaml_eq.golden.yaml rename to gold/testdata/TestExistingFiles/assert_yaml.golden.yaml diff --git a/gold/testdata/TestInvalidData/valid_json.golden.json b/gold/testdata/TestInvalidData/valid_json.golden.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/gold/testdata/TestInvalidData/valid_json.golden.json @@ -0,0 +1 @@ +{} \ No newline at end of file