Unit Testing Go Code

Unit testing Go code is one of the most pleasant testing experiences I have ever known. As a bonus your tests can also serve as documentation and examples. This is one area where the experience and expertise of the Go development team are so completely obvious.

Go testing can generally be categorized into the following:

  1. quick examples that happen to be tests,
  2. stuff that needs the standard testing package,
  3. stuff that has to be mocked up to be tested.

The first one is the easiest and cleanest for public stuff anyone using your package would use it to do.

The second comes into play usually when you need to really test some internal code to make sure you got everything right, but also occasionally for the public stuff.

The third requires careful planning of your package in general such that pieces that simply cannot realistically be tested can be replaced with mocked up copies for the sake of unit testing but ultimately will have to be tested at a higher level up in the testing cycle (system integration and user acceptance testing), where humans or more complicated automations are used. Test-driven development zealots hate the reality that not all code can be tested automatically but at least we can isolate those pieces to make a clean separation between what can be tested and what cannot.

Go Unit Testing Tips

These tips are things that were not specifically mentioned anywhere that sort of became best practices for me. Some I got from other experienced Go developers.

Use _test for Your Package and File Names When Testing Public

It’s standard to name your test file foo_test.go if you have a foo.go package containing public stuff to be tested. Usually I stick with the example form of testing as much as possible for this to I can get the maximum documentation out of them.

However, I have seen people use package foo and package foo_test in their testing but the best way is package foo_test because if forces you to do the required work to get it exactly where it will be, setup the module correctly with go mod and creates examples that look exactly like what the user will use.

Use _internal_test for File Names When Testing Private

Not adding package foo_test and just using package foo produces tests that have visibility directly into all the private stuff you should test, but produces test code that isn’t really suitable for any sort of documentation — and it shouldn’t be because you are testing private stuff.

This testing should almost always use the testing package because of the range of utility it provides — especially when setting up and tearing down testing scenarios.

💎 I really wish this were more well known for beginners because this really brings home the difference between private and public for new developers. You can learn and teach professional development habits by simply thinking of testing in this way, the testing where you pretend you are a person using your package, and the testing for yourself to make sure your internal code does what you think it is supposed to do.

I got this great tip from Mat Ryer.

Use testdata or . or _ When Needed

I use testdata a lot to put in files that will be ignored by the go build tool but any file beginning with . or _ is also ignored, which is a good thing because .git would really mess stuff up if it were seen by go build.