Skip to content

Commit

Permalink
test: add more tests and coverate report
Browse files Browse the repository at this point in the history
  • Loading branch information
g4s8 committed Dec 16, 2023
1 parent a6316b1 commit a03e026
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 9 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ jobs:
run: go build -v
- name: Test
run: go test -v
- name: Coverage report
run: |
go test -v -covermode=count -coverprofile=coverage.out
go tool cover -func=coverage.out
- name: Vet
run: go vet
- name: golangci-lint
Expand Down
126 changes: 126 additions & 0 deletions inspector_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package main

import (
"embed"
"fmt"
"io"
"os"
"path"
"testing"
)

Expand Down Expand Up @@ -55,3 +59,125 @@ func TestTagParsers(t *testing.T) {
})
}
}

//go:embed testdata
var testdata embed.FS

func TestInspector(t *testing.T) {
// envName string // environment variable name
// doc string // field documentation text
// flags docItemFlags
// envDefault string
for _, c := range []struct {
name string
typeName string
goLine int
expect []docItem
}{
{
name: "example_generate.go",
goLine: 3,
expect: []docItem{
{
envName: "FOO",
doc: "Foo stub",
},
},
},
{
name: "example_tags.go",
typeName: "Type1",
expect: []docItem{
{
envName: "SECRET",
doc: "Secret is a secret value that is read from a file.",
flags: docItemFlagFromFile,
},
{
envName: "PASSWORD",
doc: "Password is a password that is read from a file.",
flags: docItemFlagFromFile,
envDefault: "/tmp/password",
},
{
envName: "CERTIFICATE",
doc: "Certificate is a certificate that is read from a file.",
flags: docItemFlagFromFile | docItemFlagExpand,
envDefault: "${CERTIFICATE_FILE}",
},
{
envName: "SECRET_KEY",
doc: "Key is a secret key.",
flags: docItemFlagRequired,
},
{
envName: "SECRET_VAL",
doc: "SecretVal is a secret value.",
flags: docItemFlagNonEmpty | docItemFlagRequired,
},
},
},
{
name: "example_type.go",
typeName: "Type1",
expect: []docItem{
{
envName: "FOO",
doc: "Foo stub",
},
},
},
} {
t.Run(c.name, inspectorTester(c.name, c.typeName, c.goLine, c.expect))
}
}

type testOutput struct {
items []docItem
}

func (o *testOutput) writeItem(i docItem) {
o.items = append(o.items, i)
}

func copyTestFile(name string, dest string) error {
srcf, err := testdata.Open(name)
if err != nil {
return fmt.Errorf("open testdata file: %w", err)
}
defer srcf.Close()

dstf, err := os.Create(dest)
if err != nil {
return fmt.Errorf("create destination file: %w", err)
}
defer dstf.Close()

if _, err := io.Copy(dstf, srcf); err != nil {
return fmt.Errorf("copy file: %w", err)
}
return nil
}

func inspectorTester(name string, typeName string, lineN int, expect []docItem) func(*testing.T) {
return func(t *testing.T) {
var out testOutput
sourceFile := path.Join(t.TempDir(), "tmp.go")
if err := copyTestFile(path.Join("testdata", name), sourceFile); err != nil {
t.Fatal("Copy test file data", err)
}
insp := newInspector(typeName, &out, lineN)
if err := insp.inspectFile(sourceFile); err != nil {
t.Fatal("Inspector failed", err)
}
if len(out.items) != len(expect) {
t.Errorf("inspector found %d items; expected %d", len(out.items), len(expect))
}
for i := range out.items {
if out.items[i] != expect[i] {
t.Errorf("inspector found item[%d] %+v; expected %+v", i,
out.items[i], expect[i])
}
}
}
}
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func main() {
output := newMarkdownOutput(outputFile)
output.writeHeader()
defer func() {
if err := output.Close(); err != nil {
fatalf("close output: %v", err)
if err := output.dump(); err != nil {
fatalf("dump output: %v", err)
}
}()

Expand Down
9 changes: 2 additions & 7 deletions markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (
type markdownOutput struct {
out io.Writer

sb strings.Builder
closed bool
sb strings.Builder
}

func newMarkdownOutput(out io.Writer) *markdownOutput {
Expand Down Expand Up @@ -45,11 +44,7 @@ func (m *markdownOutput) writeItem(item docItem) {
m.sb.WriteString(fmt.Sprintf("- %s\n", item.doc))
}

func (m *markdownOutput) Close() error {
if m.closed {
return nil
}
m.closed = true
func (m *markdownOutput) dump() error {
if _, err := m.out.Write([]byte(m.sb.String())); err != nil {
return fmt.Errorf("write: %w", err)
}
Expand Down
85 changes: 85 additions & 0 deletions markdown_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"bufio"
"bytes"
"testing"
)

func TestMarkdown(t *testing.T) {
t.Run("header", func(t *testing.T) {
var out bytes.Buffer
mw := newMarkdownOutput(&out)
mw.writeHeader()
if err := mw.dump(); err != nil {
t.Fatal("dump markdown writer", err)
}
if out.String() != "# Environment variables\n\n" {
t.Fatal("unexpected output", out.String())
}
})
t.Run("items", func(t *testing.T) {
// envName string // environment variable name
// doc string // field documentation text
// flags docItemFlags
// envDefault string
var out bytes.Buffer
mw := newMarkdownOutput(&out)
mw.writeItem(docItem{
envName: "FOO",
doc: "foo",
})
mw.writeItem(docItem{
envName: "BAR",
doc: "bar",
envDefault: "1",
})
mw.writeItem(docItem{
envName: "BAZ",
doc: "baz",
flags: docItemFlagRequired,
})
mw.writeItem(docItem{
envName: "QUX",
doc: "qux",
flags: docItemFlagNonEmpty,
})
mw.writeItem(docItem{
envName: "QUUX",
doc: "quux",
flags: docItemFlagRequired | docItemFlagNonEmpty,
})
mw.writeItem(docItem{
envName: "CORGE",
doc: "corge",
flags: docItemFlagRequired | docItemFlagExpand,
})
mw.writeItem(docItem{
envName: "GRAULT",
doc: "grault",
flags: docItemFlagFromFile | docItemFlagExpand | docItemFlagNonEmpty,
})
if err := mw.dump(); err != nil {
t.Fatal("dump markdown writer", err)
}
expectLines := []string{
"- `FOO` - foo",
"- `BAR` (default: `1`) - bar",
"- `BAZ` (**required**) - baz",
"- `QUX` (not-empty) - qux",
"- `QUUX` (**required**, not-empty) - quux",
"- `CORGE` (**required**, expand) - corge",
"- `GRAULT` (expand, not-empty, from file) - grault",
}
scanner := bufio.NewScanner(&out)
var pos int
for scanner.Scan() {
expect := expectLines[pos]
actual := scanner.Text()
if actual != expect {
t.Fatalf("unexpected output at line %d: %q != %q", pos, actual, expect)
}
pos++
}
})
}
12 changes: 12 additions & 0 deletions testdata/example_generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package testdata

//go:generate STUB
type Type1 struct {
// Foo stub
Foo int `env:"FOO"`
}

type Type2 struct {
// Baz stub
Baz int `env:"BAZ"`
}
14 changes: 14 additions & 0 deletions testdata/example_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package testdata

type Type1 struct {
// Secret is a secret value that is read from a file.
Secret string `env:"SECRET,file"`
// Password is a password that is read from a file.
Password string `env:"PASSWORD,file" envDefault:"/tmp/password" json:"password"`
// Certificate is a certificate that is read from a file.
Certificate string `env:"CERTIFICATE,file,expand" envDefault:"${CERTIFICATE_FILE}"`
// Key is a secret key.
SecretKey string `env:"SECRET_KEY,required" json:"secret_key"`
// SecretVal is a secret value.
SecretVal string `json:"secret_val" env:"SECRET_VAL,notEmpty"`
}
11 changes: 11 additions & 0 deletions testdata/example_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package testdata

type Type1 struct {
// Foo stub
Foo int `env:"FOO"`
}

type Type2 struct {
// Baz stub
Baz int `env:"BAZ"`
}

0 comments on commit a03e026

Please sign in to comment.