Skip to content

Commit

Permalink
Merge pull request #89 from SimonBaeumer/fix-add-command
Browse files Browse the repository at this point in the history
Fix add command for existing stdout and stderr properties
  • Loading branch information
SimonBaeumer authored Sep 13, 2019
2 parents 93f45e1 + 4e08260 commit 4f3cb41
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 30 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ tmp.yml
*.out
coverage
*.exe
commander.yaml
commander.yaml
tmp
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# v1.2.1

- Fix `add` command if `stdout` or `stderr` properties were removed if a new test was added

# v1.2.0

- Add reading envrionment variables from shell
- Add `interval` option for `retries` which allows to execute a retry after a given period of time. I.e. `interval: 50ms`
- Add reading environment variables from shell, i.e. `${PATH}`
- Add `interval` option for `retries` which allows to execute a retry after a given period of time. I.e. `interval: 50ms`

# v1.1.0

Expand Down
35 changes: 13 additions & 22 deletions pkg/app/add_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,35 @@ func AddCommand(command string, existed []byte) ([]byte, error) {
return []byte{}, err
}

//If a suite existed before adding the new command it is need to parse it and re-add it
if len(existed) > 0 {
err := yaml.UnmarshalStrict(existed, &conf)
if err != nil {
panic(err.Error())
}

for k, t := range conf.Tests {
conf.Tests[k] = suite.YAMLTest{
test := suite.YAMLTest{
Title: t.Title,
Stdout: convertExpectedOut(t.Stdout.(runtime.ExpectedOut)),
Stderr: convertExpectedOut(t.Stderr.(runtime.ExpectedOut)),
Stdout: t.Stdout.(runtime.ExpectedOut),
Stderr: t.Stderr.(runtime.ExpectedOut),
ExitCode: t.ExitCode,
Config: convertConfig(t.Config),
}

//If title and command are not equal add the command property to the struct
if t.Title != t.Command {
test.Command = t.Command
}

conf.Tests[k] = test
}
}

conf.Tests[command] = suite.YAMLTest{
Title: command,
Stdout: stringOrNil(c.Stdout()),
Stderr: stringOrNil(c.Stderr()),
Stdout: runtime.ExpectedOut{Contains: []string{c.Stdout()}},
Stderr: runtime.ExpectedOut{Contains: []string{c.Stderr()}},
ExitCode: c.ExitCode(),
}

Expand All @@ -53,26 +61,9 @@ func AddCommand(command string, existed []byte) ([]byte, error) {
return out, nil
}

func stringOrNil(str string) interface{} {
if str == "" {
return nil
}
return str
}

func convertConfig(config suite.YAMLTestConfig) suite.YAMLTestConfig {
if config.Dir == "" && len(config.Env) == 0 && config.Timeout == "" {
return suite.YAMLTestConfig{}
}
return config
}

func convertExpectedOut(out runtime.ExpectedOut) interface{} {
if len(out.Contains) == 1 && len(out.Lines) == 0 && out.Exactly == "" {
return out.Contains[0]
}
if len(out.Contains) == 0 {
return nil
}
return out
}
47 changes: 47 additions & 0 deletions pkg/app/add_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,50 @@ tests:
assert.Nil(t, err)
assert.Equal(t, "tests:\n echo exists:\n exit-code: 0\n echo hello:\n exit-code: 0\n stdout: hello\n", string(content))
}

func Test_AddCommand_AddToExistingWithComplexStdStreamAssertions(t *testing.T) {
existing := []byte(`
tests:
exists:
command: echo exists
stdout:
contains:
- exists
not-contains:
- byebye
stderr:
not-contains:
- stderr not
line-count: 10
lines:
1: line1
2: line2
exit-code: 0
`)

content, err := AddCommand("echo hello", existing)

expected := []byte(`tests:
echo hello:
exit-code: 0
stdout: hello
exists:
command: echo exists
exit-code: 0
stdout:
contains:
- exists
not-contains:
- byebye
stderr:
lines:
1: line1
2: line2
line-count: 10
not-contains:
- stderr not
`)

assert.Nil(t, err)
assert.Equal(t, string(expected), string(content))
}
10 changes: 5 additions & 5 deletions pkg/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ type Expected struct {

//ExpectedOut represents the assertions on stdout and stderr
type ExpectedOut struct {
Contains []string
Lines map[int]string
Exactly string
LineCount int
NotContains []string
Contains []string `yaml:"contains,omitempty"`
Lines map[int]string `yaml:"lines,omitempty"`
Exactly string `yaml:"exactly,omitempty"`
LineCount int `yaml:"line-count,omitempty"`
NotContains []string `yaml:"not-contains,omitempty"`
}

// CommandUnderTest represents the command under test
Expand Down
53 changes: 53 additions & 0 deletions pkg/suite/yaml_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/SimonBaeumer/commander/pkg/runtime"
"gopkg.in/yaml.v2"
"reflect"
"strings"
)

Expand Down Expand Up @@ -260,3 +261,55 @@ func (y *YAMLConfig) mergeEnvironmentVariables(global YAMLTestConfig, local YAML
}
return env
}

//MarshalYAML adds custom logic to the struct to yaml conversion
func (y YAMLConfig) MarshalYAML() (interface{}, error) {
//Detect which values of the stdout/stderr assertions should be filled.
//If all values are empty except Contains it will convert it to a single string
//to match the easiest test suite definitions
for k, t := range y.Tests {
t.Stdout = convertExpectedOut(t.Stdout.(runtime.ExpectedOut))
if reflect.ValueOf(t.Stdout).Kind() == reflect.Struct {
t.Stdout = t.Stdout.(runtime.ExpectedOut)
}

t.Stderr = convertExpectedOut(t.Stderr.(runtime.ExpectedOut))
if reflect.ValueOf(t.Stderr).Kind() == reflect.Struct {
t.Stderr = t.Stderr.(runtime.ExpectedOut)
}

y.Tests[k] = t
}

return y, nil
}

func convertExpectedOut(out runtime.ExpectedOut) interface{} {
//If the property contains consists of only one element it will be set without the struct structure
if isContainsASingleNonEmptyString(out) && propertiesAreEmpty(out) {
return out.Contains[0]
}

//If the contains property only has one empty string element it should not be displayed
//in the marshaled yaml file
if len(out.Contains) == 1 && out.Contains[0] == "" {
out.Contains = nil
}

if len(out.Contains) == 0 && propertiesAreEmpty(out) {
return nil
}
return out
}

func propertiesAreEmpty(out runtime.ExpectedOut) bool {
return out.Lines == nil &&
out.Exactly == "" &&
out.LineCount == 0 &&
out.NotContains == nil
}

func isContainsASingleNonEmptyString(out runtime.ExpectedOut) bool {
return len(out.Contains) == 1 &&
out.Contains[0] != ""
}
67 changes: 67 additions & 0 deletions pkg/suite/yaml_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,70 @@ tests:

_ = ParseYAML(yaml)
}

func Test_YAMLConfig_MarshalYAML(t *testing.T) {
conf := YAMLConfig{Tests: map[string]YAMLTest{
"return_string": {
Stdout: runtime.ExpectedOut{Contains: []string{"stdout string"}},
Stderr: runtime.ExpectedOut{Contains: []string{"stderr string"}},
},
"return_struct": {
Stdout: runtime.ExpectedOut{
Contains: []string{"stdout"},
LineCount: 10,
},
Stderr: runtime.ExpectedOut{
Contains: []string{"stderr"},
LineCount: 10,
},
},
"return_nil": {
Stdout: runtime.ExpectedOut{},
Stderr: runtime.ExpectedOut{},
},
}}

out, _ := conf.MarshalYAML()
r := out.(YAMLConfig)

assert.Equal(t, "stdout string", r.Tests["return_string"].Stdout)
assert.Equal(t, "stderr string", r.Tests["return_string"].Stderr)

assert.Equal(t, conf.Tests["return_struct"].Stdout, r.Tests["return_struct"].Stdout)
assert.Equal(t, conf.Tests["return_struct"].Stderr, r.Tests["return_struct"].Stderr)

assert.Nil(t, r.Tests["return_nil"].Stdout)
assert.Nil(t, r.Tests["return_nil"].Stderr)
}

func Test_convertExpectOut_ReturnNilIfEmpty(t *testing.T) {
out := runtime.ExpectedOut{
Contains: []string{""},
}

r := convertExpectedOut(out)

assert.Nil(t, r)
}

func Test_convertExpectedOut_ReturnContainsAsString(t *testing.T) {
out := runtime.ExpectedOut{
Contains: []string{"test"},
}

r := convertExpectedOut(out)

assert.Equal(t, "test", r)
}

func Test_convertExpectedOut_ReturnFullStruct(t *testing.T) {
out := runtime.ExpectedOut{
Contains: []string{"hello", "hi"},
LineCount: 10,
Exactly: "test",
}

r := convertExpectedOut(out)

assert.Equal(t, out, r)
}

0 comments on commit 4f3cb41

Please sign in to comment.