11 Testing


This chapter covers

  • Categorizing tests and making them more robust
  • Making Go tests deterministic
  • Working with utility packages such as httptest and iotest
  • Avoiding common benchmark mistakes
  • Improving the testing process

Testing is a crucial aspect of a project’s lifecycle. It offers countless benefits, such as building confidence in an application, acting as code documentation, and making refactoring easier. Compared to some other languages, Go has strong primitives for writing tests. Throughout this chapter, we look at common mistakes that make the testing process brittle, less effective, and less accurate.

11.1 #82: Not categorizing tests

The testing pyramid is a model that groups tests into different categories (see figure 11.1). Unit tests occupy the base of the pyramid. Most tests should be unit tests: they’re cheap to write, fast to execute, and highly deterministic. Usually, as we go further up the pyramid, tests become more complex to write and slower to run, and it is more difficult to guarantee their determinism.

Figure 11.1 An example of the testing pyramid

A common technique is to be explicit about which kind of tests to run. For instance, depending on the project lifecycle stage, we may want to run only unit tests or run all the tests in the project. Not categorizing tests means potentially wasting time and effort and losing accuracy about the scope of a test. This section discusses three main ways to categorize tests in Go.

11.1.1 Build tags

11.1.2 Environment variables

11.1.3 Short mode

11.2 #83: Not enabling the -race flag

11.3 #84: Not using test execution modes

11.3.1 The parallel flag

11.3.2 The -shuffle flag

11.4 #85: Not using table-driven tests