Go > Testing and Benchmarking > Unit Testing > Testing with the testing package

Simple Unit Test in Go

This snippet demonstrates a basic unit test in Go using the `testing` package. It covers the fundamental structure of a test function and assertion.

Basic Structure of a Go Unit Test

This code defines a simple `Add` function and its corresponding test function `TestAdd`. - The `testing` package is imported. - Test functions must start with the prefix `Test` and take a `*testing.T` argument, which provides methods for reporting test failures and logging information. - Inside `TestAdd`, the `Add` function is called with sample input, and the result is compared to the expected value. - `t.Errorf` is used to report an error if the result doesn't match the expectation. The message includes the actual result and the expected result for easy debugging.

package mypackage

import "testing"

func Add(a, b int) int {
	return a + b
}

func TestAdd(t *testing.T) {
	result := Add(2, 3)
	expected := 5
	if result != expected {
		// Report an error if the result is not as expected.
		t.Errorf("Add(2, 3) = %d; expected %d", result, expected)
	}
}

Concepts Behind the Snippet

Go's unit testing framework relies on the `testing` package. Tests are functions that verify the behavior of other functions or methods. The crucial part is the assertion, where the actual output is compared against the expected output. If they don't match, the test is considered a failure.

Real-Life Use Case

Consider a function that calculates the discount price of an item based on a percentage. A unit test can verify that the discounted price is calculated correctly for various input values (e.g., positive price and discount, zero price, invalid discount percentage). This ensures the discount calculation logic is robust and accurate.

Best Practices

  • Write focused tests: Each test should focus on testing one specific aspect of the function.
  • Use descriptive test names: Choose names that clearly indicate what the test is verifying.
  • Provide informative error messages: Make sure the error messages in `t.Errorf` are clear and helpful for debugging.
  • Keep tests independent: Tests should not rely on each other; otherwise, a failure in one test might cascade into others.
  • Use table-driven tests for multiple scenarios: This is shown in the second example below.

Interview Tip

Be prepared to explain the structure of a Go test function (the `TestXxx(t *testing.T)` pattern). Also, be ready to discuss common testing tools and strategies, such as table-driven testing, mocking, and integration tests. Understanding the purpose of the `testing` package and its various methods is crucial.

When to Use Them

Use unit tests for verifying the correctness of individual functions, methods, and packages. They are especially useful for catching regressions (bugs that reappear after being fixed) and for ensuring that code changes don't break existing functionality. Unit tests form the foundation of a robust testing strategy.

Memory Footprint

Unit tests generally have a small memory footprint, as they only test individual units of code. The `testing` package itself is lightweight. Focus on cleaning up any resources used during testing (e.g., closing files, releasing database connections) to minimize memory consumption.

Alternatives

While `testing` is the standard Go package for unit testing, alternative libraries like `testify` offer more advanced assertion capabilities and mocking features. However, sticking with the standard library is often sufficient for most unit testing needs.

Pros

  • Built-in: The `testing` package is part of the Go standard library, so there are no external dependencies.
  • Simple and easy to use: The API is straightforward and easy to learn.
  • Good performance: Go's testing framework is efficient and fast.

Cons

  • Basic assertions: The built-in assertion capabilities are somewhat limited compared to more advanced testing libraries.
  • No built-in mocking: Mocking requires manual implementation or the use of external libraries.

FAQ

  • What does `t.Errorf` do?

    `t.Errorf` reports a formatted error message to the test runner. It indicates that the test has failed. The message typically includes information about the expected and actual results, making it easier to diagnose the problem.
  • How do I run my unit tests?

    Use the command `go test` in the directory containing your test files. To run tests in a specific package, use `go test `. To run all tests in subdirectories use `go test ./...`.