Tests in Go Subdirectories: Complete Guide for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Tests in Go Subdirectories: Solving the Problem Tutorials Don't Mention

\n\n

Have you ever written tests in Go and found that they work perfectly in the project root, but as soon as you move them to a subdirectory — everything breaks? Sound familiar? If so — you're not alone. The question "Golang tests in sub-directory" on Stack Overflow has gathered thousands of views. And it's no surprise: Go's documentation is dry on this topic, and beginner developers often get lost.

\n\n

In this article, we'll figure out how to properly organize Go testing using nested packages, why it's needed, and how to avoid common pitfalls. Let's go!

\n\n

Why Are Tests in Subdirectories a Pain?

\n\n

Imagine: you have a project with the following structure:

\n\n
myapp/\n├── main.go\n├── go.mod\n└── utils/\n    ├── math.go\n    └── math_test.go
\n\n

You run Go test from the root — and everything works. But when you try to run the tests from the utils folder, Go complains: "package myapp/utils is not in GOROOT". Sound familiar?

\n\n

The problem is that Go works with packages, not folders. When you create a subdirectory, you are essentially creating a new package. And tests in it need to be run considering the project's module structure. But let's take it step by step.

\n\n

Basics: How Go Sees Tests

\n\n

In Go, tests are regular files with the _test.go suffix. They can be located:

\n
    \n
  • In the same package (white-box tests) — have access to unexported functions.
  • \n
  • In a separate package with the _test suffix (black-box tests) — test the package as an external user.
  • \n
\n\n

When you place tests in a subdirectory, you create a new package. For example, the utils folder is the utils package. And the tests in it must belong to that package.

\n\n

Example of a Correct Structure

\n\n
myapp/\n├── go.mod\n├── main.go\n└── utils/\n    ├── math.go        // package utils\n    └── math_test.go   // package utils
\n\n

In the file math.go:

\n
package utils\n\nfunc Add(a, b int) int {\n    return a + b\n}
\n\n

In the file math_test.go:

\n
package utils\n\nimport "testing"\n\nfunc TestAdd(t *testing.T) {\n    result := Add(2, 3)\n    if result != 5 {\n        t.Errorf("Expected 5, got %d", result)\n    }\n}
\n\n

Now run the tests from the project root:

\n
go test ./utils/
\n\n

Or from the utils folder:

\n
cd utils\ngo test
\n\n

Everything works! But what if you have a more complex structure?

\n\n

Nested Subdirectories: Deeper Than It Seems

\n\n

Let's say you have a project with this structure:

\n\n
myapp/\n├── go.mod\n├── main.go\n└── services/\n    ├── user/\n    │   ├── user.go\n    │   └── user_test.go\n    └── order/\n        ├── order.go\n        └── order_test.go
\n\n

Here, each subdirectory is a separate package. To run all tests recursively, use three dots:

\n\n
go test ./...
\n\n

This command will find all packages in the project and run their tests. Very convenient for CI/CD!

\n\n

What If Tests Are in the Same Folder as the Code?

\n\n

Sometimes developers put tests in the same folder as the main code. This is fine for small projects. But for large projects, it's better to place tests in separate subdirectories — it keeps the structure cleaner.

\n\n

Common Mistakes and Their Solutions

\n\n

Let's break down the most frequent problems beginners face when working with Golang tests in sub-directory.

\n\n

Error 1: "package is not in GOROOT"

\n

Cause: You are trying to run a test from a subdirectory without specifying the module. Go doesn't know which module the package belongs to.

\n

Solution: Make sure you have a go.mod file in the root

Blogs

Book Recommendations