Hey! In this blog post, we'll guide you through the basics of writing and running tests in Go. We'll take a simple function that reverses a string and walk through writing tests for it, running the tests to identify issues, and then fixing the implementation until all tests pass. Additionally, we'll demonstrate how to structure your tests using t.Run to organize multiple test cases efficiently.
Step 1: Set Up Your Project
First, let's create a new package for our string utilities
mkdir stringutils cd stringutils
Initialise a Go module for your project:
go mod init stringutils
We'll be using the testify package for assertions in our tests. Install it with:
go get github.com/stretchr/testify
Step 2: Write Your First Test
Create a test file where we will write our first test:
touch stringutils_test.go
Now, let's write a test for the Reverse function:
// stringutils_test.go package stringutil import ( "testing" "github.com/stretchr/testify/assert" ) func TestReverse(t *testing.T) { // Test case: Reverse a simple string input := "hello" expected := "olleh" // Call the function to test result := Reverse(input) // Assert the result using testify's assert package assert.Equal(t, expected, result, "they should be equal") }
Make sure your project is up to date with required dependencies:
go mod tidy
Step 3: Run the Test and Make It Fail
Run the test with:
go test
You should see an error like this:
# stringutils [stringutils.test] ./stringutils_test.go:15:12: undefined: Reverse FAIL stringutils [build failed]
The error indicates that the Reverse function is undefined. This is expected because we haven't written the function yet.
Step 4: Create the Reverse Function
Let's create the stringutils.go file and add a basic implementation of the Reverse function to fix the first error:
touch stringutils.go
Add the following code:
package stringutil // Reverse returns the given string reversed. func Reverse(s string) string { return "" }
Now, when you run the test again, you should see a different error:
go test
The output should look something like this:
--- FAIL: TestReverse (0.00s) stringutils_test.go:18: Error Trace: /workspace/go/stringutils/stringutils_test.go:18 Error: Not equal: expected: "olleh" actual : "" Diff: --- Expected +++ Actual @@ -1 +1 @@ -olleh + Test: TestReverse Messages: they should be equal FAIL exit status 1 FAIL stringutils 0.265s
The test is failing because the Reverse function is returning an empty string, not the expected reversed string.
Step 5: Implement the Reverse Function
Let's implement the Reverse function properly:
package stringutil // Reverse returns the given string reversed. func Reverse(s string) string { reversedStr := "" // Loop through the string backwards for i := len(s) - 1; i >= 0; i-- { // Append each character to the reversed string reversedStr += string(s[i]) } return reversedStr }
Run the test again:
go test
You should see a success message:
PASS ok stringutils 0.263s
Step 6: Add More Tests with t.Run()
Let's add more tests using t.Run() to structure them as sub-tests:
// stringutils_test.go package stringutil import ( "testing" "github.com/stretchr/testify/assert" ) func TestReverse(t *testing.T) { t.Run("Simple string", func(t *testing.T) { input := "hello" expected := "olleh" result := Reverse(input) assert.Equal(t, expected, result, "they should be equal") }) t.Run("String with spaces and punctuation", func(t *testing.T) { input := "Go, Gophers!" expected := "!srehpoG ,oG" result := Reverse(input) assert.Equal(t, expected, result, "they should be equal") }) t.Run("Empty string", func(t *testing.T) { input := "" expected := "" result := Reverse(input) assert.Equal(t, expected, result, "they should be equal") }) }
Run the tests again:
go test
You should see all tests passing:
PASS ok stringutils 3.055s
Conclusion
In this post, we've walked through setting up a simple Go project, writing a test-first function using TDD, and structuring tests using t.Run(). This should give you a solid foundation to start testing in Go and applying TDD practices in your future projects. Happy coding!