This article explains how to write unit tests in Go, covering best practices, test structure, and testing functions from different packages.
In this lesson, we’ll explore how to write unit tests in Go while observing best practices for testing. Go’s built-in test runner and framework seamlessly integrate with standard language tooling, allowing you to execute tests simply by running:
Copy
Ask AI
go test ./
This command automatically discovers and runs tests in the current directory and its subdirectories. Remember that test files should be separate from your main package code and must have filenames ending with _test.go.Below, you’ll learn how to test a function that determines whether an integer is even.
Begin by creating a function called checkEven in your main package. This function accepts an integer argument and returns "YES" if the number is even; otherwise, it returns "NO".
Copy
Ask AI
package mainfunc checkEven(i int) string { if i%2 == 0 { return "YES" } return "NO"}func main() { // Application entry point; can be left empty for testing purposes.}
To test the checkEven function, create a file named process_test.go in the same directory. In Go, test functions must start with a capital letter Test. The following example shows how to write a test case for checkEven:
Copy
Ask AI
package mainimport "testing"func TestCheckEven(t *testing.T) { i := 10 expected := "YES" res := checkEven(i) if expected != res { t.Errorf("expected: %v, got: %v", expected, res) }}
When you run:
Copy
Ask AI
go test .
the test will execute and pass if checkEven returns the correct output.
To see a failing test in action, you can intentionally set the expected string to "YESs":
Copy
Ask AI
package mainimport "testing"func TestCheckEven(t *testing.T) { i := 10 expected := "YESs" // Intentionally incorrect for demonstration purposes res := checkEven(i) if expected != res { t.Errorf("expected: %v, got: %v", expected, res) }}
Executing the test with the modified expectation produces output similar to:
Copy
Ask AI
go test .--- FAIL: TestCheckEven (0.00s) process_test.go:10: expected: YESs, got: YESFAILFAIL example.com/learn 0.407s
It is crucial to always begin your test function names with a capital T. If you name a test function with a lowercase t (e.g., func testCheckEven(t *testing.T) { ... }), the test runner will not recognize it:
Copy
Ask AI
> go test .ok example.com/learn (cached) [no tests to run]
Testing Exported Functions from a Separate Package
Another effective strategy is testing functions from an external package. You may move your code into its own package (for example, process) and then write tests that import this package.Imagine moving your process.go file into a subdirectory named process, and updating the package name accordingly:
Alternatively, you can maintain a dedicated directory (such as tests) for your test code. This method is suitable when testing exported functions. After moving your test file into the tests directory, your test might look like this:
Copy
Ask AI
package mainimport ( "example.com/learn/process" "testing")func TestCheckEven(t *testing.T) { i := 10 expected := "YES" res := process.CheckEven(i) if expected != res { t.Errorf("expected: %v, got: %v", expected, res) }}
Executing tests from within the tests directory with:
Copy
Ask AI
go test .
will produce:
Copy
Ask AI
ok example.com/learn/tests 0.449s
This approach is effective for verifying only the publicly exported functions. However, note that testing internal (non-exported) functions requires placing the tests within the same package as the code.
Always name test functions starting with a capital Test.
For internal functions, write tests in the same package; for exported functions, consider using a separate test package.
Keep your test code modular and reflective of actual consumer usage.
Consolidate similar code examples to maintain clarity and conciseness in documentation.
By following these best practices, you ensure that your test code remains clear and effective, while also making your projects easier to maintain and scale.For additional information, consider exploring Go Testing Documentation.