Practical Go. Amit Saha
Чтение книги онлайн.

Читать онлайн книгу Practical Go - Amit Saha страница 13

Название: Practical Go

Автор: Amit Saha

Издательство: John Wiley & Sons Limited

Жанр: Программы

Серия:

isbn: 9781119773832

isbn:

СКАЧАТЬ standard library's testing package contains everything you need to write tests to verify the behavior of your application.

      Let's consider the parseArgs() function first. It is defined as follows:

      func parseArgs(args []string) (config, error) {}

      It has one input: a slice of strings representing the command-line arguments specified to the program during invocation. The return values are a value of type config and a value of type error .

      The testConfig structure will be used to encapsulate a specific test case: a slice of strings representing the input command-line arguments in the args field, expected error value returned in the err field, and the expected config value returned in the embedded config struct field:

      An example test case is

      { args: []string{"-h"}, err: nil, config: config{printUsage: true, numTimes: 0}, },

      This test case verifies the behavior when -h is specified as the command-line argument when executing the application.

      We add a few more test cases and initialize a slice of test cases as follows:

      tests := []testConfig{ { args: []string{"-h"}, err: nil, config: config{printUsage: true, numTimes: 0}, }, { args: []string{"10"}, err: nil, config: config{printUsage: false, numTimes: 10}, }, { args: []string{"abc"}, err: errors.New("strconv.Atoi: parsing \"abc\": invalid syntax"), config: config{printUsage: false, numTimes: 0}, }, { args: []string{"1", "foo"}, err: errors.New("Invalid number of arguments"), config: config{printUsage: false, numTimes: 0}, }, }

      In the same directory as you saved Listing 1.1, save Listing 1.2 into a file called parse_flags_test.go. Now run the test using the go test command:

      $ go test -v === RUN TestParseArgs --- PASS: TestParseArgs (0.00s) PASS ok github.com/practicalgo/code/chap1/manual-parse 0.093

      Passing in the -v flag when running go test also displays the test functions that are being run and the result.

      Next, consider the validateArgs() function defined as func validateArgs(c config) error. Based on the function specification, we will once again define a slice of test cases. However, instead of defining a named struct type, we will use an anonymous struct type instead as follows:

      // chap1/manual-parse/validate_args_test.go package main import ( "errors" "testing" ) func TestValidateArgs(t *testing.T) { // TODO Insert definition tests[] slice as above for _, tc := range tests { err := validateArgs(tc.c) if tc. err != nil && err.Error() != tc.err.Error() { t.Errorf("Expected error to be: %v, got: %v\n", tc.err, err) } if tc.err == nil && err != nil { t.Errorf("Expected nil error, got: %v\n", err) } } }

      In the same subdirectory as Listing 1.2, save Listing 1.3 to a file called validate_args_test.go. Now run the tests using the go test command. It will now run both the TestParseFlags and TestValidateArgs tests.

      tests := []struct { c config input string output string err error }{ { c: config{printUsage: true}, output: usageString, }, { c: config{numTimes: 5}, input: "", output: strings.Repeat("Your name please? Press the Enter key when done.\n", 1), err: errors.New("You didn't enter your name"), }, { c: config{numTimes: 5}, input: "Bill Bryson", output: "Your name please? Press the Enter key when done.\n" + strings.Repeat("Nice to meet you Bill Bryson\n", 5), }, }

      The field c is a config object representing the incoming configuration, input is the test input received by the program from the user interactively, output is the expected output, and err represents any error that is expected based on the test input and configuration.

      When you write a test for a program where you have to mimic an input from the user, this is how you can create a io.Reader from a string:

       r := strings.NewReader(tc.input)

      Thus, when the getName() function is called with io.Reader r as created above, calling scanner.Text() will return the string in tc.input .

      // СКАЧАТЬ