Skip to content

Commit 8b39413

Browse files
committed
ref(_tests): add a custom matcher just for command output
1 parent eaec7c8 commit 8b39413

5 files changed

Lines changed: 118 additions & 43 deletions

File tree

_tests/apps_test.go

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,34 @@ var _ = Describe("Apps", func() {
1414
})
1515

1616
It("can't get app info", func() {
17-
output, err := execute("deis info -a %s", app1Name)
18-
Expect(err).To(HaveOccurred())
19-
Expect(output).To(ContainSubstring("NOT FOUND"))
17+
Expect(execute("deis info -a %s", app1Name)).To(SucceedWithOutput(ContainSubstring("NOT FOUND")))
2018
})
2119

2220
It("can't get app logs", func() {
23-
output, err := execute("deis logs -a %s", app1Name)
24-
Expect(err).To(HaveOccurred())
25-
Expect(output).To(ContainSubstring("NOT FOUND"))
21+
out := execute("deis logs -a %s", app1Name)
22+
Expect(out.err).To(HaveOccurred())
23+
Expect(out.str).To(ContainSubstring("NOT FOUND"))
2624
})
2725

2826
// TODO: this currently returns "Error: json: cannot unmarshal object into Go value of type []interface {}"
2927
XIt("can't run a command in the app environment", func() {
30-
output, err := execute("deis apps:run echo Hello, 世界")
31-
Expect(err).To(HaveOccurred())
32-
Expect(output).To(ContainSubstring("NOT FOUND"))
28+
out := execute("deis apps:run echo Hello, 世界")
29+
Expect(out.err).To(HaveOccurred())
30+
Expect(out.str).To(ContainSubstring("NOT FOUND"))
3331
})
3432

3533
It("can create an app", func() {
36-
output, err := execute("deis apps:create %s", app1Name)
37-
Expect(err).NotTo(HaveOccurred())
38-
Expect(output).To(SatisfyAll(
34+
Expect(execute("deis apps:create %s", app1Name)).To(SucceedWithOutput(
3935
ContainSubstring("Creating Application... done, created %s", app1Name),
4036
ContainSubstring("Git remote deis added"),
41-
ContainSubstring("remote available at ")))
42-
output, err = execute("deis apps:destroy --confirm=%s", app1Name)
43-
Expect(err).NotTo(HaveOccurred())
44-
Expect(output).To(SatisfyAll(
37+
ContainSubstring("remote available at "),
38+
))
39+
40+
Expect(execute("deis apps:destroy --confirm=%s", app1Name)).To(SucceedWithOutput(
4541
ContainSubstring("Destroying %s...", app1Name),
4642
ContainSubstring("done in "),
47-
ContainSubstring("Git remote deis removed")))
43+
ContainSubstring("Git remote deis removed"),
44+
))
4845
})
4946

5047
It("can create an app with no git remote", func() {

_tests/auth_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ var _ = Describe("Auth", func() {
1212
})
1313

1414
It("won't print the current user", func() {
15-
output, err := execute("deis auth:whoami")
16-
Expect(err).To(HaveOccurred())
17-
Expect(output).To(ContainSubstring("Not logged in."))
18-
Expect(output).NotTo(ContainSubstring(testUser))
15+
Expect(execute("deis auth:whoami")).To(BeASuccessfulCommandWithOutputMatching(
16+
ContainSubstring("Not logged in."),
17+
ContainSubstring(testUser),
18+
))
1919
})
2020
})
2121

@@ -30,21 +30,21 @@ var _ = Describe("Auth", func() {
3030

3131
It("won't register twice", func() {
3232
cmd := "deis register %s --username=%s --password=%s --email=%s"
33-
output, err := execute(cmd, url, testUser, testPassword, testEmail)
34-
Expect(err).To(HaveOccurred())
35-
Expect(output).To(ContainSubstring("Registration failed"))
33+
out := execute(cmd, url, testUser, testPassword, testEmail)
34+
Expect(out.err).To(HaveOccurred())
35+
Expect(out.str).To(ContainSubstring("Registration failed"))
3636
})
3737

3838
It("prints the current user", func() {
39-
output, err := execute("deis auth:whoami")
40-
Expect(err).NotTo(HaveOccurred())
41-
Expect(output).To(ContainSubstring("You are %s", testUser))
39+
Expect(execute("deis auth:whoami")).To(SucceedWithOutput(
40+
ContainSubstring("You are %s", testUser),
41+
))
4242
})
4343

4444
It("regenerates the token for the current user", func() {
45-
output, err := execute("deis auth:regenerate")
46-
Expect(err).NotTo(HaveOccurred())
47-
Expect(output).To(ContainSubstring("Token Regenerated"))
45+
Expect(execute("deis auth:regenerate")).To(SucceedWithOutput(
46+
ContainSubstring("Token Regenerated"),
47+
))
4848
})
4949
})
5050

_tests/cmd_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package _tests_test
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"fmt"
7+
"github.com/onsi/gomega/types"
8+
"os/exec"
9+
"strings"
10+
)
11+
12+
// cmdOut is the output of a command. it's used by cmdMatcher to match on
13+
type cmdOut struct {
14+
args []string
15+
str string
16+
err error
17+
}
18+
19+
// execute executes the command generated by fmt.Sprintf(cmdLine, args...) and returns its output as a cmdOut structure.
20+
// this structure can then be matched upon using the SucceedWithOutput matcher below
21+
func execute(cmdLine string, args ...interface{}) *cmdOut {
22+
var stdout, stderr bytes.Buffer
23+
var cmd *exec.Cmd
24+
cmd = exec.Command("/bin/sh", "-c", fmt.Sprintf(cmdLine, args...))
25+
cmd.Stdout, cmd.Stderr = &stdout, &stderr
26+
ret := &cmdOut{}
27+
ret.args = cmd.Args
28+
ret.str = stdout.String()
29+
if err := cmd.Run(); err != nil {
30+
ret.err = err
31+
return ret
32+
}
33+
return ret
34+
}
35+
36+
var (
37+
errExpectedCmdOut = errors.New("cmdMatcher expects a *cmdOut")
38+
errFailedCmd = errors.New("command failed")
39+
)
40+
41+
// Command
42+
type successfulCmdMatcher struct {
43+
// will be filled in when Match is called
44+
cmdo *cmdOut
45+
matchers []types.GomegaMatcher
46+
}
47+
48+
// SucceedWithOutput returns a matcher that will match on a *cmdOut, ensuring that the command returned no error
49+
// and its output matches all the given matchers
50+
func SucceedWithOutput(matchers ...types.GomegaMatcher) types.GomegaMatcher {
51+
return &successfulCmdMatcher{matchers: matchers}
52+
}
53+
54+
// Match is the interface implementation of github.com/onsi/gomega/types.GomegaMatcher
55+
func (c *successfulCmdMatcher) Match(actual interface{}) (bool, error) {
56+
cmdo, ok := actual.(*cmdOut)
57+
if !ok {
58+
return false, errExpectedCmdOut
59+
}
60+
c.cmdo = cmdo
61+
if cmdo.err != nil {
62+
return false, errFailedCmd
63+
}
64+
return SatisfyAll(c.matchers...)
65+
}
66+
67+
// FailureMessage is the interface implementation of github.com/onsi/gomega/types.GomegaMatcher
68+
func (c *successfulCmdMatcher) FailureMessage(actual interface{}) string {
69+
if c.cmdo == nil {
70+
return "command failed, but wasn't recorded"
71+
}
72+
return fmt.Sprintf("command %s errored.\noutput:\n%s\nerror:%s\n",
73+
strings.Join(c.cmdo.args, " "),
74+
c.cmdo.str,
75+
c.cmdo.err,
76+
)
77+
}
78+
79+
// NegatedFailureMessage is the interface implementation of github.com/onsi/gomega/types.GomegaMatcher
80+
func (c *successfulCmdMatcher) NegatedFailureMessage(actual interface{}) string {
81+
if c.cmdo == nil {
82+
return "command failed, but wasn't recorded"
83+
}
84+
85+
return fmt.Sprintf("command %s errored.\noutput:\n%s\nerror:%s\n",
86+
strings.Join(c.cmdo.args, " "),
87+
c.cmdo.str,
88+
c.cmdo.err,
89+
)
90+
}

_tests/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var _ = Describe("Config", func() {
1414

1515
It("can create a new app", func() {
1616
output, err := execute("deis apps:create %s", appName)
17-
Expect(err).NotTo(HaveOccurred())
17+
Expect(err).To(BeNil())
1818
Expect(output).To(SatisfyAll(
1919
ContainSubstring("Creating Application... done, created %s", appName),
2020
ContainSubstring("Git remote deis added"),

_tests/tests_suite_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package _tests_test
22

33
import (
4-
"bytes"
54
"fmt"
65
"math/rand"
76
"os"
@@ -105,17 +104,6 @@ func logout() {
105104
Expect(output).To(Equal("Logged out\n"))
106105
}
107106

108-
func execute(cmdLine string, args ...interface{}) (string, error) {
109-
var stdout, stderr bytes.Buffer
110-
var cmd *exec.Cmd
111-
cmd = exec.Command("/bin/sh", "-c", fmt.Sprintf(cmdLine, args...))
112-
cmd.Stdout, cmd.Stderr = &stdout, &stderr
113-
if err := cmd.Run(); err != nil {
114-
return stderr.String(), err
115-
}
116-
return stdout.String(), nil
117-
}
118-
119107
func createKey(name string) {
120108
var home string
121109
if user, err := user.Current(); err != nil {

0 commit comments

Comments
 (0)