@@ -4,14 +4,23 @@ import (
44 "bytes"
55 "os"
66 "os/exec"
7- "strconv"
87 "strings"
98 "testing"
109)
1110
1211type Utility struct {
1312 * testing.T
14- ID string // The resource ID created by Create
13+ ID string // The resource ID created by a step, if needed
14+ }
15+
16+ type Step struct {
17+ Name string
18+ Run func (* Utility )
19+ Deferred bool // If true, run only at the end as cleanup
20+ }
21+
22+ type TestCase struct {
23+ Steps []Step
1524}
1625
1726// Run executes the CLI using 'go run main.go' from the ./src directory with the given arguments and optional stdin, returning combined output and error.
@@ -30,78 +39,97 @@ func (u *Utility) Run(args string, stdin ...string) (string, error) {
3039 return out .String () + errBuf .String (), err
3140}
3241
33- type Step func (* Utility )
34-
35- type CLITest struct {
36- Create Step
37- Get [2 ]Step
38- Delete Step
39- Steps []Step
40- }
41-
42- func (ct * CLITest ) Run (t * testing.T ) {
42+ func (tc * TestCase ) Run (t * testing.T ) {
4343 util := & Utility {T : t }
44- defer func () {
45- if util .ID != "" {
46- ct .Delete (util )
44+ // Run non-deferred steps
45+ for _ , step := range tc .Steps {
46+ if step .Deferred {
47+ continue
4748 }
48- }()
49-
50- t .Run ("Create" , func (t * testing.T ) {
51- util .T = t
52- ct .Create (util )
53- })
54- t .Run ("Get" , func (t * testing.T ) {
55- util .T = t
56- ct .Get [0 ](util ) // Should exist after create
57- })
58- for i , step := range ct .Steps {
59- t .Run ("Step " + strconv .Itoa (i ), func (t * testing.T ) {
49+ t .Run (step .Name , func (t * testing.T ) {
50+ util .T = t
51+ step .Run (util )
52+ })
53+ }
54+ // Run deferred steps
55+ for _ , step := range tc .Steps {
56+ if ! step .Deferred {
57+ continue
58+ }
59+ t .Run (step .Name , func (t * testing.T ) {
6060 util .T = t
61- step (util )
61+ step . Run (util )
6262 })
6363 }
64- t .Run ("Delete" , func (t * testing.T ) {
65- util .T = t
66- ct .Delete (util )
67- ct .Get [1 ](util ) // Should not exist after delete
68- util .ID = "" // Mark as deleted so defer doesn't try again
69- })
7064}
7165
7266func Create (cmd string , input string ) Step {
73- return func (u * Utility ) {
74- out , err := u .Run (cmd , input )
75- if err != nil {
76- u .Fatalf ("create failed: %v\n out: %s" , err , out )
77- }
78- u .ID = strings .TrimSpace (out )
79- if u .ID == "" {
80- u .Fatalf ("expected ID, got: %q" , out )
81- }
67+ return Step {
68+ Name : "Create" ,
69+ Run : func (u * Utility ) {
70+ out , err := u .Run (cmd , input )
71+ if err != nil {
72+ u .Fatalf ("create failed: %v\n out: %s" , err , out )
73+ }
74+ u .ID = strings .TrimSpace (out )
75+ if u .ID == "" {
76+ u .Fatalf ("expected ID, got: %q" , out )
77+ }
78+ },
8279 }
8380}
8481
85- func Get (cmd string ) [2 ]Step {
86- return [2 ]Step {func (u * Utility ) {
87- out , err := u .Run (cmd + " " + u .ID )
88- if err != nil {
89- u .Fatalf ("get failed: %v\n out: %s" , err , out )
90- }
91- }, func (u * Utility ) {
92- out , err := u .Run (cmd + " " + u .ID )
93- lower := strings .ToLower (out )
94- if err == nil || ! (strings .Contains (lower , "not found" ) || strings .Contains (lower , "missing" ) || strings .Contains (lower , "does not exist on this account" )) {
95- u .Fatalf ("expected get after delete to fail with not found, got: %v\n out: %s" , err , out )
96- }
97- }}
82+ func Delete (cmd string ) Step {
83+ return Step {
84+ Name : "Delete" ,
85+ Deferred : true ,
86+ Run : func (u * Utility ) {
87+ out , err := u .Run (cmd + " " + u .ID )
88+ if err != nil {
89+ u .Fatalf ("delete failed: %v\n out: %s" , err , out )
90+ }
91+ },
92+ }
9893}
9994
100- func Delete (cmd string ) Step {
101- return func (u * Utility ) {
102- out , err := u .Run (cmd + " " + u .ID )
103- if err != nil {
104- u .Fatalf ("delete failed: %v\n out: %s" , err , out )
105- }
95+ // Get returns a Step that runs the get command and validates the output using the provided function.
96+ func Get (cmd string , validate func (u * Utility , stdout string )) Step {
97+ return Step {
98+ Name : "Get" ,
99+ Run : func (u * Utility ) {
100+ out , err := u .Run (cmd + " " + u .ID )
101+ if err != nil {
102+ u .Fatalf ("get failed: %v\n out: %s" , err , out )
103+ }
104+ validate (u , out )
105+ },
106+ }
107+ }
108+
109+ // List returns a Step that runs the list command and validates the output using the provided function.
110+ func List (cmd string , validate func (u * Utility , stdout string )) Step {
111+ return Step {
112+ Name : "List" ,
113+ Run : func (u * Utility ) {
114+ out , err := u .Run (cmd )
115+ if err != nil {
116+ u .Fatalf ("list failed: %v\n out: %s" , err , out )
117+ }
118+ validate (u , out )
119+ },
120+ }
121+ }
122+
123+ // Update returns a Step that runs the update command with input and validates the output using the provided function.
124+ func Update (cmd string , input string , validate func (u * Utility , stdout string )) Step {
125+ return Step {
126+ Name : "Update" ,
127+ Run : func (u * Utility ) {
128+ out , err := u .Run (cmd + " " + u .ID + " -f -" , input )
129+ if err != nil {
130+ u .Fatalf ("update failed: %v\n out: %s" , err , out )
131+ }
132+ validate (u , out )
133+ },
106134 }
107135}
0 commit comments