github.com/fnando/bolt@v0.0.4-0.20231107225351-5241e4d187b8/cmd/bolt_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "os" 7 "os/exec" 8 "path" 9 "regexp" 10 "runtime" 11 "testing" 12 "time" 13 14 c "github.com/fnando/bolt/common" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func init() { 19 _, filename, _, _ := runtime.Caller(0) 20 dir := path.Join(path.Dir(filename), "..") 21 err := os.Chdir(dir) 22 23 if err != nil { 24 panic(err) 25 } 26 } 27 28 type execResult struct { 29 exitcode int 30 stdout string 31 stderr string 32 } 33 34 func read(path string) string { 35 contents, err := os.ReadFile(path) 36 37 if err != nil { 38 panic(err) 39 } 40 41 return string(contents) 42 } 43 44 func normalizeElapsedText(input string) string { 45 re := regexp.MustCompile(`Finished in ([^,]+)`) 46 return re.ReplaceAllString(input, "Finished in 0s") 47 } 48 49 func run(args []string, env []string) (execResult, error) { 50 args = append([]string{"run", "./cmd/bolt.go"}, args...) 51 stdout := bytes.NewBufferString("") 52 stderr := bytes.NewBufferString("") 53 dir, _ := os.Getwd() 54 cmd := exec.Command("go", args...) 55 cmd.Stderr = stderr 56 cmd.Stdout = stdout 57 cmd.Env = append(os.Environ(), env...) 58 cmd.Dir = dir 59 err := cmd.Start() 60 61 if err != nil { 62 return execResult{ 63 stdout: stdout.String(), 64 stderr: stderr.String(), 65 exitcode: -1, 66 }, err 67 } 68 69 err = cmd.Wait() 70 71 result := execResult{ 72 stdout: stdout.String(), 73 stderr: stderr.String(), 74 exitcode: 0, 75 } 76 77 if exiterr, ok := err.(*exec.ExitError); ok { 78 result.exitcode = exiterr.ExitCode() 79 80 return result, nil 81 } 82 83 if err != nil { 84 return execResult{ 85 stdout: stdout.String(), 86 stderr: stderr.String(), 87 exitcode: -1, 88 }, err 89 } 90 91 return result, err 92 } 93 94 func TestMain(m *testing.M) { 95 c.Clock.Now = time.Now 96 exitcode := m.Run() 97 os.Exit(exitcode) 98 } 99 100 func TestRunCommand(t *testing.T) { 101 require.NoError(t, nil) 102 103 t.Run("Help", func(t *testing.T) { 104 result, err := run([]string{"run", "--help"}, []string{}) 105 106 require.NoError(t, err) 107 require.Equal(t, read("test/expected/run-help.txt"), result.stdout) 108 require.Equal(t, 0, result.exitcode) 109 }) 110 111 t.Run("SuccessReplayFile", func(t *testing.T) { 112 c.Clock.Now = func() time.Time { 113 t, _ := time.Parse(time.RFC3339, "2023-10-31T12:15:22.773212-07:00") 114 return t 115 } 116 result, err := run( 117 []string{"run", "--no-color", "--replay", "test/replays/run-pass.txt"}, 118 []string{}, 119 ) 120 121 require.NoError(t, err) 122 require.Equal(t, read("test/expected/run-pass.txt"), normalizeElapsedText(result.stdout)) 123 require.Equal(t, 0, result.exitcode) 124 }) 125 126 t.Run("FailReplayFile", func(t *testing.T) { 127 c.Clock.Now = func() time.Time { 128 t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00") 129 return t 130 } 131 result, err := run( 132 []string{"run", "--no-color", "--replay", "test/replays/run-fail.txt"}, 133 []string{}, 134 ) 135 136 require.NoError(t, err) 137 require.Equal(t, read("test/expected/run-fail.txt"), normalizeElapsedText(result.stdout)) 138 require.Contains(t, result.stderr, "exit status 3") 139 require.Equal(t, 1, result.exitcode) 140 }) 141 142 t.Run("SkipReplayFile", func(t *testing.T) { 143 c.Clock.Now = func() time.Time { 144 t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00") 145 return t 146 } 147 result, err := run( 148 []string{"run", "--no-color", "--replay", "test/replays/run-skip.txt"}, 149 []string{}, 150 ) 151 152 require.NoError(t, err) 153 require.Equal(t, read("test/expected/run-skip.txt"), normalizeElapsedText(result.stdout)) 154 require.Equal(t, 0, result.exitcode) 155 }) 156 157 t.Run("CustomSymbols", func(t *testing.T) { 158 result, err := run( 159 []string{"run", "--no-color", "--replay", "test/replays/run-mixed.txt"}, 160 []string{"BOLT_FAIL_SYMBOL=❌", "BOLT_PASS_SYMBOL=⚡️", "BOLT_SKIP_SYMBOL=😴"}, 161 ) 162 163 require.NoError(t, err) 164 require.Contains(t, result.stdout, "⚡️⚡️❌❌❌⚡️⚡️⚡️😴😴") 165 }) 166 167 t.Run("ColorOutput", func(t *testing.T) { 168 result, err := run( 169 []string{"run", "--replay", "test/replays/run-mixed.txt"}, 170 []string{}, 171 ) 172 173 require.NoError(t, err) 174 require.Equal( 175 t, 176 read("test/expected/run-mixed-color.txt"), 177 normalizeElapsedText(result.stdout), 178 ) 179 require.Contains(t, result.stderr, "exit status 3") 180 require.Equal(t, 1, result.exitcode) 181 }) 182 183 t.Run("CustomColorOutput", func(t *testing.T) { 184 result, err := run( 185 []string{"run", "--replay", "test/replays/run-mixed.txt"}, 186 []string{ 187 "BOLT_TEXT_COLOR=31", 188 "BOLT_FAIL_COLOR=32", 189 "BOLT_PASS_COLOR=33", 190 "BOLT_SKIP_COLOR=34", 191 "BOLT_DETAIL_COLOR=35", 192 }, 193 ) 194 195 require.NoError(t, err) 196 require.Equal( 197 t, 198 read("test/expected/run-mixed-custom-color.txt"), 199 normalizeElapsedText(result.stdout), 200 ) 201 require.Contains(t, result.stderr, "exit status 3") 202 require.Equal(t, 1, result.exitcode) 203 }) 204 205 t.Run("ReplayError", func(t *testing.T) { 206 result, err := run( 207 []string{"run", "--replay", "test/replays/run-error.txt"}, 208 []string{}, 209 ) 210 211 require.NoError(t, err) 212 require.Equal(t, read("test/expected/run-error.txt"), result.stdout) 213 require.Equal(t, 1, result.exitcode) 214 }) 215 216 t.Run("ReplayNoTests", func(t *testing.T) { 217 result, err := run( 218 []string{"run", "--no-color", "--replay", "test/replays/run-no-tests.txt"}, 219 []string{}, 220 ) 221 222 require.NoError(t, err) 223 require.Equal(t, read("test/expected/run-no-tests.txt"), normalizeElapsedText(result.stdout)) 224 require.Equal(t, 0, result.exitcode) 225 }) 226 227 t.Run("JSON", func(t *testing.T) { 228 c.Clock.Now = func() time.Time { 229 t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00") 230 return t 231 } 232 233 result, err := run( 234 []string{"run", "--reporter", "json", "--replay", "test/replays/run-mixed.txt"}, 235 []string{}, 236 ) 237 238 require.NoError(t, err) 239 240 var data any 241 err = json.Unmarshal([]byte(result.stdout), &data) 242 require.NoError(t, err) 243 244 require.Contains(t, result.stderr, "exit status 3") 245 require.Equal(t, 1, result.exitcode) 246 }) 247 248 t.Run("PostRunCommand", func(t *testing.T) { 249 _, err := run( 250 []string{"run", "--no-color", "--debug", "--replay", "test/replays/run-mixed.txt", "--post-run-command", "env | grep BOLT | sort > test/tmp/env"}, 251 []string{}, 252 ) 253 254 require.NoError(t, err) 255 256 content := read("test/tmp/env") 257 258 require.Contains(t, content, "BOLT_TEST_COUNT=10\n") 259 require.Contains(t, content, "BOLT_PASS_COUNT=5\n") 260 require.Contains(t, content, "BOLT_FAIL_COUNT=3\n") 261 require.Contains(t, content, "BOLT_SKIP_COUNT=2\n") 262 require.Contains(t, content, "BOLT_BENCHMARK_COUNT=0\n") 263 require.Contains(t, content, "BOLT_SUMMARY=") 264 require.Contains(t, content, "BOLT_TITLE=Failed!\n") 265 require.Contains(t, content, "BOLT_ELAPSED=") 266 require.Contains(t, content, "BOLT_ELAPSED_NANOSECONDS=") 267 }) 268 }