The goal of this exercise is to practice generics and testing package in Go.
One note, you can do these steps in reverse, i.e. writting the tests first and implementing the data structure afterwards. You may know this technique as test-driven development.
The Go standard libary implements some data structures in the container package (linked-list, heap, ring buffer to be precise). Unfortunately, these data structures do not use generics and use the any
interface.
- Choose the data structure you would like to implement.
- linked-list
- queue
- heap
- ring buffer
- or any other
- Create a new module and a new Go file.
- The names are completely up to you, e.g.
<data-structure>.go
.
- The names are completely up to you, e.g.
- Implement the data structure.
- No need to implement all of the methods you can think of, just some will do so the data structure is usable.
- Do not create the
main()
function. We are writting a library not an executable.
Having an implementation is nice, but we can't be sure it works right without properly testing it.
- Create a new Go file named
<data-structure>_test.go
in the same package.- Go uses the
_test.go
suffix for all of the test files. - If it lacks this suffix, the
go test
command will never run the tests in it.
- Go uses the
- Implement a couple of tests for your data structure.
- All the test functions are prefixed with
Test
in their names and receivet *testing.T
as argument. - If any function lacks this prefix, the
go test
command will never run it. - Test functions with the
*t.Testing
parameter missing will not even compile. - One example of such test function:
- All the test functions are prefixed with
func TestQueueEmpty(t *testing.T) {
q := New[rune]()
actual := q.Values()
if len(actual) != 0 {
t.Errorf("%d != %d", 0, actual)
}
}
It worth pointing out that comparing expected and actual state just using the if statements and the *t.Testing
parameter is quite tidious. Luckily, assertion libraries exist. One such library is called testify.
- To import testify execute:
go get github.com/stretchr/testify
. - Use it to test you implementation.
- The previous test could be rewriten like so:
func TestQueueEmpty(t *testing.T) {
q := New[rune]()
actual := q.Values()
assert.Equal(t, 0, len(actual))
}
- Executing the tests is as simple as running:
go test ./...
- You can also add the
-v
for verbosity. - You can also specify which specific tests to run with
-run X
flag. This command runs test with names that match theX
regex. - As always,
go help test
is your friend.
- You can also add the
- To generate coverage of your tests add the
-cover
flag to yourgo test
like so:go test -cover -v ./...
. - To generate a coverage profile execute:
go test -coverprofile=c.out ./...
. - You can inspect the code coverage using the cover tool:
go tool cover -html="c.out"
.- This can help you to check out code your tests do not cover.