Getting Started with Go: Test, Build and Run Your App

Mike Dyne
Evendyne
Published in
5 min readJan 26, 2023

Writing quality software always requires appropriate testing to ensure your app behaves correctly and does what it’s intended to do. After all tests are green, compiled languages like Golang require you to build the binary first, for execution. This article aims to provide you a basic understanding of how these processes are done In Go.

Testify: Go packages that provide many tools for testifying that your code will behave as you intend.

Test

Go has a built-in testing framework that makes it easy to write and run tests for your code. To write a test, you will need to create a file with a _test.go suffix. For example, if you have a file called service.go, you can create a test file in the same directory called service_test.go.In your test file, you can write test functions that follow a specific format. A test function has the following signature:

func TestXXX(t *testing.T) {
// test code goes here
}

The XXX in the function name should be replaced with a descriptive name for the test. The t *testing.T parameter is used to report test failures and log messages. Inside the test function, you can write code for your test. You can use the t.Error or t.Errorf function to report a test failure. For example:

func TestAdd(t *testing.T) {
result := add(1, 2)
if result != 3 {
t.Errorf("Expected 3, got %d", result)
}
}

You can also organize your tests into different parts by using the t.Run method. For example:

func TestParallel(t *testing.T) {
t.Run("group1", func(t *testing.T) {
// test cases for group1
})

t.Run("group2", func(t *testing.T) {
// test cases for group2
})
}

This allows you to group related tests together, and run specific groups of tests by passing the group name as the argument to the -run flag.

With Visual Studio Code, you can generate table tests for your Go package with a few clicks. First, you need to have the Go extension installed. Then, open the file containing the function you want to test, and place the cursor on the function name. Right-click or Cmd + Shift + P, and select “Generate test function” from the context menu. This will create a new test file with a table test for the function, where you can add test cases.
Here is a simple function that checks if a string slice contains an item:

func Contains(set []string, e string) bool {
for _, v := range set {
if v == e {
return true
}
}
return false
}

And here is the generated table test output for “Go: Generate Unit Tests For Function”:

func TestContains(t *testing.T) {
type args struct {
set []string
e string
}
tests := []struct {
name string
args args
want bool
}{
// Add test cases.
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Contains(tt.args.set, tt.args.e); got != tt.want {
t.Errorf("Contains() = %v, want %v", got, tt.want)
}
})
}
}

In Go, assertions are used to test the validity of a boolean expression. If the expression is true, the assertion passes. If the expression is false, the assertion fails and an error is raised. There are a few different libraries that you can use to write assertions. The one I recommend is github.com/stretchr/testify/assert. This is a simple and lightweight assertion library that provides a set of functions for making assertions. It can be used to test values, types, and error messages. Here is an example that demonstrates how to use assert to test the equality of two values:

func TestAdd(t *testing.T) {
result := add(1, 2)
assert.Equal(t, 3, result, "Expected 3")
}

In this example, we are using the Equal function to test that the result variable is equal to 3. If result is not equal to 3, the assertion will fail and an error will be raised.

Testify also includes a suite package that allows you to organize your tests into test suites, which can be run as a group. A test suite is defined as a struct that embeds the suite.Suite struct. For example:

type MySuite struct {
suite.Suite
}

You can then define tests as methods on this struct that have the Test, Benchmark, or Example prefix. For example:

func (s *MySuite) TestAdd() {
result := 1 + 1
s.Equal(2, result)
}

To run the test suite, you’ll need to create a new instance of it and pass it to the suite.Run function. You can also group different test suites together and run them all at once. For example:

func TestMySuite(t *testing.T) {
suite.Run(t, new(MySuite))
}

func TestAllSuites(t *testing.T) {
suite.Run(t, new(MySuite))
suite.Run(t, new(AnotherSuite))
}

By using testify, you can take advantage of many additional functionalities:

  • You can use TearDownSuite,SetupSuite, TearDownTest and SetupTest methods to perform additional setup and cleanup tasks before and after the entire test suite and individual test cases.
  • Other functionalities include assert, mock, http and require packages which help making test cases more readable and easy to write and test http handlers, external calls and dependencies respectively.

Finally, to run your tests, use the following command :

go test

This will run all of the tests in the current directory and its subdirectories. Let’s say you want to run tests only in pkg subdirectories, then you can append ./pkg/... at the end of the go test command.

The following parameters can be used with the command:

  • -v: verbose output, which shows all test cases that are run
  • -cover: generates a coverage report for the package
  • -run: only runs tests that match the specified regular expression
  • -count: number of times to run each test (default is 1)
  • -parallel: number of tests to run simultaneously (default is the value of GOMAXPROCS)

To set parallel execution on/off, use -parallel=1 to run one test at a time or -parallel=n to run n tests at a time.

Build and Run

To build an executable file for your Go app, you can use the go build command. This will create a binary file that you can run on any machine. Here is an example to build the binary:

go build -o my-app main.go

This will create a binary file called my-app in the current directory. You might have to set permissions of the binary to be executable with chmod +x my-app. Run this file by typing:

./my-app

An alternative way to build and run your application, is by running the following command:

go run main.go

Note that this way the executable file is not going to be located in the current directory.

Wrapping Up

That’s it! You have learned the basics of testing, building, and running a Go application. However, there is still more to learn about these processes, especially testing. Keep an eye out for future advanced articles about it.

--

--

Mike Dyne
Evendyne

I write articles in various software engineering topics. Read every story from me by subscribing here: https://medium.com/@mikedyne/membership