When executing unit tests in Go, we typically use the standard library testing. Here are the specific steps and some practical tips for executing unit tests:
1. Creating Test Files
In Go, test code is typically located in files ending with _test.go. These files reside in the same package as the source code files they test. For example, if you have a file named calculator.go, you should create a test file named calculator_test.go.
2. Writing Test Functions
In the test file, each test function must start with Test and accept a parameter of type *testing.T. For example:
gopackage calculator import "testing" func TestAdd(t *testing.T) { result := Add(1, 2) expected := 3 if result != expected { t.Errorf("Add(1, 2) = %d; expected %d", result, expected) } }
3. Using t.Run() for Sub-tests
To organize test cases more effectively and share setup code, you can use t.Run() to define sub-tests:
gofunc TestAdd(t *testing.T) { t.Run("1+2", func(t *testing.T) { if Add(1, 2) != 3 { t.Fail() } }) t.Run("1+0", func(t *testing.T) { if Add(1, 0) != 1 { t.Fail() } }) }
4. Running Tests
You can run tests using Go's command-line tool. Use the following command:
bashgo test
This command automatically locates all *_test.go files and executes the test functions within them.
5. Using Table-Driven Tests
Table-driven tests are a common method for organizing tests in Go, making tests clearer and easier to extend:
gofunc TestAdd(t *testing.T) { var tests = []struct { a, b, expected int }{ {1, 2, 3}, {1, 0, 1}, {-1, -1, -2}, } for _, tt := range tests { testname := fmt.Sprintf("%d+%d", tt.a, tt.b) t.Run(testname, func(t *testing.T) { ans := Add(tt.a, tt.b) if ans != tt.expected { t.Errorf("got %d, want %d", ans, tt.expected) } }) } }
6. Checking Code Coverage
To check the code coverage of your tests, you can use the go test -cover command, which tells you the percentage of code covered by tests. This is an important aspect for improving code quality.
bashgo test -cover
Summary
Using Go's testing package makes it convenient to execute unit tests. By combining test functions, sub-tests, table-driven tests, and code coverage tools, you can build a robust and maintainable testing environment.