Simple, intuitive CLI framework for Go pkg.go.dev/go.followtheprocess.codes/cli
go cli
0

Configure Feed

Select the types of activity you want to include in your feed.

Bump up test coverage (#181)

authored by

Tom Fleet and committed by
GitHub
(Nov 9, 2025, 1:34 PM UTC) c54816e9 a8e6f55c

+141 -23
-5
command.go
··· 181 181 command string // The command string for the example. 182 182 } 183 183 184 - // String implements [fmt.Stringer] for [Example]. 185 - func (e example) String() string { 186 - return fmt.Sprintf("\n # %s\n $ %s\n", e.comment, e.command) 187 - } 188 - 189 184 // Execute parses the flags and arguments, and invokes the Command's Run 190 185 // function, returning any error. 191 186 //
+22
command_test.go
··· 64 64 }, 65 65 wantErr: true, 66 66 }, 67 + { 68 + name: "bad arg", 69 + stdout: "", 70 + stderr: "", 71 + options: []cli.Option{ 72 + cli.OverrideArgs([]string{"arg1", "notanumber"}), // Provided arg for 'second' is not an int 73 + cli.Arg(new(string), "first", "The first arg"), 74 + cli.Arg(new(int), "second", "The second arg"), 75 + }, 76 + wantErr: true, 77 + }, 78 + { 79 + name: "missing required argument", 80 + stdout: "", 81 + stderr: "", 82 + options: []cli.Option{ 83 + cli.OverrideArgs([]string{"hello"}), // "second" is not provided 84 + cli.Arg(new(string), "first", "The first word"), // Expect the positional arguments 85 + cli.Arg(new(string), "second", "The second word"), 86 + }, 87 + wantErr: true, 88 + }, 67 89 } 68 90 69 91 for _, tt := range tests {
+53 -18
internal/arg/arg_test.go
··· 26 26 err = intArg.Set("42") 27 27 test.Ok(t, err) 28 28 test.Equal(t, i, 42) 29 - test.Equal(t, intArg.Type(), "int") 29 + test.Equal(t, intArg.Type(), format.TypeInt) 30 30 test.Equal(t, intArg.String(), "42") 31 + test.Equal(t, intArg.Usage(), "Set an int value") 31 32 test.Equal(t, intArg.Default(), "") 32 33 }) 33 34 ··· 51 52 err = intArg.Set("42") 52 53 test.Ok(t, err) 53 54 test.Equal(t, i, int8(42)) 54 - test.Equal(t, intArg.Type(), "int8") 55 + test.Equal(t, intArg.Type(), format.TypeInt8) 56 + test.Equal(t, intArg.Usage(), "Set an int8 value") 55 57 test.Equal(t, intArg.String(), "42") 56 58 }) 57 59 ··· 75 77 err = intArg.Set("42") 76 78 test.Ok(t, err) 77 79 test.Equal(t, i, int16(42)) 78 - test.Equal(t, intArg.Type(), "int16") 80 + test.Equal(t, intArg.Type(), format.TypeInt16) 81 + test.Equal(t, intArg.Usage(), "Set an int16 value") 79 82 test.Equal(t, intArg.String(), "42") 80 83 }) 81 84 ··· 99 102 err = intArg.Set("42") 100 103 test.Ok(t, err) 101 104 test.Equal(t, i, int32(42)) 102 - test.Equal(t, intArg.Type(), "int32") 105 + test.Equal(t, intArg.Type(), format.TypeInt32) 106 + test.Equal(t, intArg.Usage(), "Set an int32 value") 103 107 test.Equal(t, intArg.String(), "42") 104 108 }) 105 109 ··· 123 127 err = intArg.Set("42") 124 128 test.Ok(t, err) 125 129 test.Equal(t, i, int64(42)) 126 - test.Equal(t, intArg.Type(), "int64") 130 + test.Equal(t, intArg.Type(), format.TypeInt64) 131 + test.Equal(t, intArg.Usage(), "Set an int64 value") 127 132 test.Equal(t, intArg.String(), "42") 128 133 }) 129 134 ··· 147 152 err = intArg.Set("42") 148 153 test.Ok(t, err) 149 154 test.Equal(t, i, 42) 150 - test.Equal(t, intArg.Type(), "uint") 155 + test.Equal(t, intArg.Type(), format.TypeUint) 156 + test.Equal(t, intArg.Usage(), "Set a uint value") 151 157 test.Equal(t, intArg.String(), "42") 152 158 }) 153 159 ··· 172 178 test.Ok(t, err) 173 179 test.Equal(t, i, uint8(42)) 174 180 test.Equal(t, intArg.Type(), "uint8") 181 + test.Equal(t, intArg.Usage(), "Set a uint8 value") 175 182 test.Equal(t, intArg.String(), "42") 176 183 }) 177 184 ··· 195 202 err = intArg.Set("42") 196 203 test.Ok(t, err) 197 204 test.Equal(t, i, uint16(42)) 198 - test.Equal(t, intArg.Type(), "uint16") 205 + test.Equal(t, intArg.Type(), format.TypeUint16) 206 + test.Equal(t, intArg.Usage(), "Set a uint16 value") 199 207 test.Equal(t, intArg.String(), "42") 200 208 }) 201 209 ··· 219 227 err = intArg.Set("42") 220 228 test.Ok(t, err) 221 229 test.Equal(t, i, uint32(42)) 222 - test.Equal(t, intArg.Type(), "uint32") 230 + test.Equal(t, intArg.Type(), format.TypeUint32) 231 + test.Equal(t, intArg.Usage(), "Set a uint32 value") 223 232 test.Equal(t, intArg.String(), "42") 224 233 }) 225 234 ··· 243 252 err = intArg.Set("42") 244 253 test.Ok(t, err) 245 254 test.Equal(t, i, uint64(42)) 246 - test.Equal(t, intArg.Type(), "uint64") 255 + test.Equal(t, intArg.Type(), format.TypeUint64) 256 + test.Equal(t, intArg.Usage(), "Set a uint64 value") 247 257 test.Equal(t, intArg.String(), "42") 248 258 }) 249 259 ··· 267 277 err = intArg.Set("42") 268 278 test.Ok(t, err) 269 279 test.Equal(t, i, uintptr(42)) 270 - test.Equal(t, intArg.Type(), "uintptr") 280 + test.Equal(t, intArg.Type(), format.TypeUintptr) 281 + test.Equal(t, intArg.Usage(), "Set a uintptr value") 271 282 test.Equal(t, intArg.String(), "42") 272 283 }) 273 284 ··· 291 302 err = floatArg.Set("3.14159") 292 303 test.Ok(t, err) 293 304 test.Equal(t, f, 3.14159) 294 - test.Equal(t, floatArg.Type(), "float32") 305 + test.Equal(t, floatArg.Type(), format.TypeFloat32) 306 + test.Equal(t, floatArg.Usage(), "Set a float32 value") 295 307 test.Equal(t, floatArg.String(), "3.14159") 296 308 }) 297 309 ··· 315 327 err = floatArg.Set("3.14159") 316 328 test.Ok(t, err) 317 329 test.Equal(t, f, 3.14159) 318 - test.Equal(t, floatArg.Type(), "float64") 330 + test.Equal(t, floatArg.Type(), format.TypeFloat64) 331 + test.Equal(t, floatArg.Usage(), "Set a float64 value") 319 332 test.Equal(t, floatArg.String(), "3.14159") 320 333 }) 321 334 ··· 339 352 err = boolArg.Set(format.True) 340 353 test.Ok(t, err) 341 354 test.Equal(t, b, true) 342 - test.Equal(t, boolArg.Type(), "bool") 355 + test.Equal(t, boolArg.Type(), format.TypeBool) 356 + test.Equal(t, boolArg.Usage(), "Set a bool value") 343 357 test.Equal(t, boolArg.String(), format.True) 344 358 }) 345 359 ··· 365 379 err = strArg.Set("newvalue") 366 380 test.Ok(t, err) 367 381 test.Equal(t, str, "newvalue") 368 - test.Equal(t, strArg.Type(), "string") 382 + test.Equal(t, strArg.Type(), format.TypeString) 383 + test.Equal(t, strArg.Usage(), "Set a string value") 369 384 test.Equal(t, strArg.String(), "newvalue") 370 385 }) 371 386 ··· 378 393 err = byteArg.Set("5e") 379 394 test.Ok(t, err) 380 395 test.EqualFunc(t, byt, []byte("^"), bytes.Equal) 381 - test.Equal(t, byteArg.Type(), "bytesHex") 396 + test.Equal(t, byteArg.Type(), format.TypeBytesHex) 397 + test.Equal(t, byteArg.Usage(), "Set a byte slice value") 382 398 test.Equal(t, byteArg.String(), "5e") 383 399 }) 384 400 ··· 405 421 want, err := time.Parse(time.RFC3339, "2024-07-17T07:38:05Z") 406 422 test.Ok(t, err) 407 423 test.Equal(t, tyme, want) 408 - test.Equal(t, timeArg.Type(), "time") 424 + test.Equal(t, timeArg.Type(), format.TypeTime) 425 + test.Equal(t, timeArg.Usage(), "Set a time value") 409 426 test.Equal(t, timeArg.String(), "2024-07-17T07:38:05Z") 410 427 }) 411 428 ··· 432 449 want, err := time.ParseDuration("300ms") 433 450 test.Ok(t, err) 434 451 test.Equal(t, duration, want) 435 - test.Equal(t, durationArg.Type(), "duration") 452 + test.Equal(t, durationArg.Type(), format.TypeDuration) 453 + test.Equal(t, durationArg.Usage(), "Set a duration value") 436 454 test.Equal(t, durationArg.String(), "300ms") 437 455 }) 438 456 ··· 456 474 err = ipArg.Set("192.0.2.1") 457 475 test.Ok(t, err) 458 476 test.DiffBytes(t, ip, net.ParseIP("192.0.2.1")) 459 - test.Equal(t, ipArg.Type(), "ip") 477 + test.Equal(t, ipArg.Type(), format.TypeIP) 478 + test.Equal(t, ipArg.Usage(), "Set an IP address") 460 479 test.Equal(t, ipArg.String(), "192.0.2.1") 461 480 }) 462 481 ··· 470 489 test.Err(t, err) 471 490 test.True(t, errors.Is(err, parse.Err)) 472 491 }) 492 + } 493 + 494 + func TestDefaults(t *testing.T) { 495 + str, err := arg.New(new(string), "str", "A string", arg.Config[string]{DefaultValue: pointer("hello")}) 496 + test.Ok(t, err) 497 + 498 + intArg, err := arg.New(new(int), "int", "A string", arg.Config[int]{DefaultValue: pointer(27)}) 499 + test.Ok(t, err) 500 + 501 + test.Equal(t, str.Default(), "hello") 502 + test.Equal(t, intArg.Default(), "27") 503 + } 504 + 505 + // pointer creates a new variable of the given value and returns its pointer. 506 + func pointer[T any](value T) *T { 507 + return &value 473 508 }
+66
internal/parse/parse_test.go
··· 1 1 package parse //nolint:testpackage // I need the base and bits values and don't want to export them. 2 2 3 3 import ( 4 + "errors" 4 5 "strconv" 5 6 "testing" 6 7 "testing/quick" 8 + 9 + "go.followtheprocess.codes/test" 7 10 ) 8 11 9 12 // These are basically all just testing that I haven't broken anything ··· 11 14 // by hand. 12 15 13 16 func TestInt(t *testing.T) { 17 + // Check a basic happy path then let quick handle the rest 18 + got, err := Int("5") 19 + test.Ok(t, err) 20 + test.Equal(t, got, 5) 21 + 14 22 test := Int 15 23 16 24 reference := func(str string) (int, error) { ··· 24 32 } 25 33 26 34 func TestInt8(t *testing.T) { 35 + got, err := Int8("4") 36 + test.Ok(t, err) 37 + test.Equal(t, got, 4) 38 + 27 39 test := Int8 28 40 29 41 reference := func(str string) (int8, error) { ··· 37 49 } 38 50 39 51 func TestInt16(t *testing.T) { 52 + got, err := Int16("32") 53 + test.Ok(t, err) 54 + test.Equal(t, got, 32) 55 + 40 56 test := Int16 41 57 42 58 reference := func(str string) (int16, error) { ··· 50 66 } 51 67 52 68 func TestInt32(t *testing.T) { 69 + got, err := Int32("12") 70 + test.Ok(t, err) 71 + test.Equal(t, got, 12) 72 + 53 73 test := Int32 54 74 55 75 reference := func(str string) (int32, error) { ··· 63 83 } 64 84 65 85 func TestInt64(t *testing.T) { 86 + got, err := Int64("27") 87 + test.Ok(t, err) 88 + test.Equal(t, got, 27) 89 + 66 90 test := Int64 67 91 68 92 reference := func(str string) (int64, error) { ··· 76 100 } 77 101 78 102 func TestUint(t *testing.T) { 103 + got, err := Uint("2") 104 + test.Ok(t, err) 105 + test.Equal(t, got, 2) 106 + 79 107 test := Uint 80 108 81 109 reference := func(str string) (uint, error) { ··· 89 117 } 90 118 91 119 func TestUint8(t *testing.T) { 120 + got, err := Uint8("8") 121 + test.Ok(t, err) 122 + test.Equal(t, got, 8) 123 + 92 124 test := Uint8 93 125 94 126 reference := func(str string) (uint8, error) { ··· 102 134 } 103 135 104 136 func TestUint16(t *testing.T) { 137 + got, err := Uint16("7") 138 + test.Ok(t, err) 139 + test.Equal(t, got, 7) 140 + 105 141 test := Uint16 106 142 107 143 reference := func(str string) (uint16, error) { ··· 115 151 } 116 152 117 153 func TestUint32(t *testing.T) { 154 + got, err := Uint32("47") 155 + test.Ok(t, err) 156 + test.Equal(t, got, 47) 157 + 118 158 test := Uint32 119 159 120 160 reference := func(str string) (uint32, error) { ··· 128 168 } 129 169 130 170 func TestUint64(t *testing.T) { 171 + got, err := Uint64("102") 172 + test.Ok(t, err) 173 + test.Equal(t, got, 102) 174 + 131 175 test := Uint64 132 176 133 177 reference := func(str string) (uint64, error) { ··· 141 185 } 142 186 143 187 func TestFloat32(t *testing.T) { 188 + got, err := Float32("102.8975") 189 + test.Ok(t, err) 190 + test.NearlyEqual(t, got, 102.8975) 191 + 144 192 test := Float32 145 193 146 194 reference := func(str string) (float32, error) { ··· 154 202 } 155 203 156 204 func TestFloat64(t *testing.T) { 205 + got, err := Float64("916156.123") 206 + test.Ok(t, err) 207 + test.NearlyEqual(t, got, 916156.123) 208 + 157 209 test := Float64 158 210 159 211 reference := func(str string) (float64, error) { ··· 164 216 if err := quick.CheckEqual(test, reference, nil); err != nil { 165 217 t.Error(err) 166 218 } 219 + } 220 + 221 + func TestError(t *testing.T) { 222 + got := Error(KindArgument, "test", "blah", "string", errors.New("underlying")) 223 + want := `parse error: argument "test" received invalid value "blah" (expected string): underlying` 224 + 225 + test.Equal(t, got.Error(), want) 226 + } 227 + 228 + func TestErrorSlice(t *testing.T) { 229 + got := ErrorSlice(KindArgument, "test", "blah", "string", errors.New("underlying")) 230 + want := `parse error: argument "test" (type string) cannot append element "blah": underlying` 231 + 232 + test.Equal(t, got.Error(), want) 167 233 }