Create the first test for your program

The convention in Go is to put unit tests alongside the code that they test rather than in a different directory. This has the advantage of giving a very visible way of seeing what has tests and what doesn’t. All test files are named *_test.go; anything named that way will not be added to the final binary, but will be taken into account by go test.

Create a file main_test.go and add the following code:

package main

import (
    "testing"
)

// All test function names should follow the TestAbc pattern and must take an
// argument of type *testing.T, conventionally named t.
func TestHelloWorld(t *testing.T) {
    val := HelloWorld()
    if val != "hello world" {
        t.Fail()
    }
}

Here we have imported the testing package and defined a test. The test calls a HelloWorld function (to be defined) and check that the value returned matches a given value.

To run this test run the following command:

go test

To get more verbose output, add -v:

go test -v

To see the coverage stats run:

go test -cover

You should see the test fail. Now let’s change main.go to make it pass. Reopen main.go and change it to look like the following:

package main

import (
    "fmt"
)

// This is a public/exported function from the package. Exported functions must
// start with an Uppercase letter. As shown by the signature, the return type of
// this function is a string and it takes no arguments.
func HelloWorld() string {
    return "hello world"
}

func main() {
    fmt.Println(HelloWorld())
}

Run the tests again, and you should see success!

go test

Pro tip: having exported names in a main package is somewhat useless, since you are not supposed to be importing that package from another one. But it is fundamental to understand that Go uses the case of the first character in identifier names instead of private/public keywords to determine visibility.

That is very nice when you are reading code. For instance, it is easy to tell that Println is a public function defined in the fmt package. That package may have private definitions, such that you can never do something like fmt.privatefunc().


If you are coming from another language, you are certainly missing assertion methods, what is commonly used in xUnit-style test frameworks. Go’s testing package takes a different approach, notably simpler.

You are given a reference t to a *testing.T value, that allows you to communicate with the test framework. The basic action is to mark the test as failed. All the rest of the test code is normal Go code, using the same language features you’d use elsewhere, like if and for constructs, function calls, variable declarations and assignments.

We’ll see in future chapters how powerful that idea is, as it allows for testing more with less boilerplate code, e.g., using table driven tests.

https://github.com/RHCloudServices/golang-intro


See also