diff --git a/integration/cli_test.go b/integration/cli_test.go index a097a0b..87dad43 100644 --- a/integration/cli_test.go +++ b/integration/cli_test.go @@ -11,17 +11,18 @@ import ( "testing" "reflect" - "strings" "github.com/kr/pretty" ) +// In the following tests, there's a lot going on. +// Please have a look at the following article for a longer explanation: +// http://lucapette.me/writing-integration-tests-for-a-go-cli-application + var update = flag.Bool("update", false, "update golden files") const binaryName = "fakedata" -var binaryPath string - func diff(expected, actual interface{}) []string { return pretty.Diff(expected, actual) } @@ -56,7 +57,6 @@ func TestCliArgs(t *testing.T) { name string args []string fixture string - match func(string, string) bool }{ { name: "no arguments", @@ -118,27 +118,14 @@ func TestCliArgs(t *testing.T) { args: []string{"-f=sql", "-t=USERS", "int,42..42", "enum,foo..foo"}, fixture: "sql-format-with-table-name.golden", }, - { - name: "file generator", - args: []string{"file,integration/file.golden"}, - fixture: "file.golden", - match: func(actual, expected string) bool { - for _, line := range strings.Split(actual, "\n") { - if !strings.Contains(expected+"\n", line+"\n") { - return false - } - } - return true - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cmd := exec.Command(binaryPath, tt.args...) + cmd := exec.Command(binaryName, tt.args...) output, err := cmd.CombinedOutput() if err != nil { - t.Fatal(err, "\n", string(output)) + t.Fatalf("output: %s\nerr: %v", output, err) } if *update { @@ -148,33 +135,43 @@ func TestCliArgs(t *testing.T) { actual := string(output) expected := loadFixture(t, tt.fixture) - if tt.match != nil { - if !tt.match(actual, expected) { - t.Fatalf("values do not match: \n%v\n%v", actual, expected) - } - } else if !reflect.DeepEqual(actual, expected) { + if !reflect.DeepEqual(actual, expected) { t.Fatalf("diff: %v", diff(expected, actual)) } }) } } -func TestCliErr(t *testing.T) { +func TestFileGenerator(t *testing.T) { tests := []struct { - name string - args []string + name string + args []string + fixture string + wantErr bool }{ - {"no file", []string{"file"}}, - {"no file,", []string{"file,"}}, - {"no file,''", []string{"file,''"}}, - {`no file,""`, []string{`file,""`}}, - {"file does not exist", []string{`file,'this file does not exist.txt'`}}, + {"no file", []string{"file"}, "path-empty.golden", true}, + {"no file,", []string{"file,"}, "path-empty.golden", true}, + {"file does not exist", []string{`file,'this file does not exist.txt'`}, "file-empty.golden", true}, + {"file exists", []string{`file,integration/file.txt`}, "file-exist.golden", false}, + {"file exists with quotes", []string{`file,'integration/file.txt'`}, "file-exist.golden", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := exec.Command(binaryPath, tt.args...).Run(); err == nil { - t.Fatalf("expected to fail with args: %v", tt.args) + cmd := exec.Command(binaryName, tt.args...) + output, err := cmd.CombinedOutput() + if (err != nil) != tt.wantErr { + t.Fatalf("%s\nexpected (err != nil) to be %v, but got %v. err: %v", output, tt.wantErr, err != nil, err) + } + if *update { + writeFixture(t, tt.fixture, output) + } + + actual := string(output) + expected := loadFixture(t, tt.fixture) + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("diff: %v", diff(expected, actual)) } }) } @@ -192,11 +189,5 @@ func TestMain(m *testing.M) { fmt.Printf("could not make binary for %s: %v", binaryName, err) os.Exit(1) } - binaryPath, err = filepath.Abs(binaryName) - if err != nil { - fmt.Printf("could not get binary path: %v", err) - os.Exit(1) - } - os.Exit(m.Run()) } diff --git a/integration/file-empty.golden b/integration/file-empty.golden new file mode 100644 index 0000000..65c8397 --- /dev/null +++ b/integration/file-empty.golden @@ -0,0 +1 @@ +could not read file this file does not exist.txt: open this file does not exist.txt: no such file or directory \ No newline at end of file diff --git a/integration/file-exist.golden b/integration/file-exist.golden new file mode 100644 index 0000000..705d9f4 --- /dev/null +++ b/integration/file-exist.golden @@ -0,0 +1,10 @@ +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file diff --git a/integration/file.golden b/integration/file.golden deleted file mode 100644 index c9e9e05..0000000 --- a/integration/file.golden +++ /dev/null @@ -1,10 +0,0 @@ -one -two -three -four -five -six -seven -eight -nine -ten diff --git a/integration/file.txt b/integration/file.txt new file mode 100644 index 0000000..1293e19 --- /dev/null +++ b/integration/file.txt @@ -0,0 +1,10 @@ +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file +from-an-existing-file \ No newline at end of file diff --git a/integration/path-empty.golden b/integration/path-empty.golden new file mode 100644 index 0000000..8e9bc78 --- /dev/null +++ b/integration/path-empty.golden @@ -0,0 +1 @@ +file: no file path given \ No newline at end of file diff --git a/pkg/fakedata/generator.go b/pkg/fakedata/generator.go index 9ed0c10..3db16a1 100644 --- a/pkg/fakedata/generator.go +++ b/pkg/fakedata/generator.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "log" "math/rand" + "os" "sort" "strconv" "strings" @@ -181,22 +182,25 @@ var enum = func(column Column) string { var fileCache map[string][]string var file = func(column Column) string { - p := column.Constraints - if p == "" { - log.Fatalf("%s: no file path given", column.Name) - } - // Try to get file from cache - f := fileCache[p] - // Load file if cache is empty - if f == nil { - content, err := ioutil.ReadFile(p) + constraint := column.Constraints + if len(constraint) == 0 { + fmt.Printf("%s: no file path given", column.Name) + os.Exit(1) + } + + filePath := strings.Trim(constraint, "'\"") + + list, ok := fileCache[filePath] + if !ok { + content, err := ioutil.ReadFile(filePath) if err != nil { - log.Fatalf("%s: no readable file found at '%s'", column.Name, p) + fmt.Printf("could not read file %s: %v", filePath, err) + os.Exit(1) } - f = strings.Split(string(content), "\n") + list = strings.Split(string(content), "\n") } - // Return random line - return f[rand.Intn(len(f))] + + return list[rand.Intn(len(list))] } func init() {