Reader small image

You're reading from  Hands-On Software Engineering with Golang

Product typeBook
Published inJan 2020
Reading LevelIntermediate
PublisherPackt
ISBN-139781838554491
Edition1st Edition
Languages
Right arrow
Author (1)
Achilleas Anagnostopoulos
Achilleas Anagnostopoulos
author image
Achilleas Anagnostopoulos

Achilleas Anagnostopoulos has been writing code in a multitude of programming languages since the mid 90s. His main interest lies in building scalable, microservice-based distributed systems where components are interconnected via gRPC or message queues. Achilleas has over 4 years of experience building production-grade systems using Go and occasionally enjoys pushing the language to its limits through his experimental gopher-os project: a 64-bit kernel written entirely in Go. He is currently a member of the Juju team at Canonical, contributing to one of the largest open source Go code bases in existence.
Read more about Achilleas Anagnostopoulos

Right arrow

The Art of Testing

"Program testing can be used to show the presence of bugs, but never to show their absence!"
- Edsger Dijkstra

Software systems are destined to grow and evolve over time. Open or closed source software projects have one thing in common: their complexity seems to follow an upward curve as the number of engineers working on the code base increases. To this end, having a comprehensive set of tests for the code base is of paramount importance. This chapter performs a deep dive into the different types of testing that can be applied to Go projects.

The following topics will be covered in this chapter:

  • Identifying the differences between high-level primitives such as stubs, mocks, spies, and fake objects that you can use while writing unit tests as substitutes for objects that are used inside the code under test
  • Comparing black-box and white-box testing...

Technical requirements

The full code for the topics discussed within this chapter have been published to this book's GitHub repository under the Chapter04 folder.

You can access this book's GitHub repository by going to https://github.com/PacktPublishing/Hands-On-Software-Engineering-with-Golang.

To get you up and running as quickly as possible, each example project includes a makefile that defines the following set of targets:

Makefile target Description
deps Install any required dependencies
test Run all the tests and report coverage
lint Check for lint errors

As with all the chapters in this book, you will need a fairly recent version of Go, which you can download at https://golang.org/dl/.

Unit testing

By definition, a unit is the smallest possible bit of code that we can test. In the context of Go programming, this would typically be a single function. However, according to the SOLID design principles that we explored in the previous chapters, each Go package could also be construed as an independent unit and tested as such.

The term unit testing refers to the process of testing each unit of an application in isolation to verify that its behavior conforms to a particular set of specifications.

In this section, we will dive into the different methodologies of unit testing at our disposal (black- versus white-box testing). We will also examine strategies for making our code easier to unit test and cover the built-in Go testing packages, as well as third-party packages, that are designed to make writing tests more streamlined.

...

Integration versus functional testing

In this section, we will attempt to dispel any confusion between the definitions of two very important and useful types of testing: integration tests and functional tests.

Integration tests

Integration tests pick up from where unit testing left off. Whereas unit testing ensures that each individual unit of a system works correctly in isolation, integration testing ensures that different units (or services, in a microservice architecture) interoperate correctly.

Let's consider a hypothetical scenario where we are building an e-shop application. Following the SOLID design principles, we have split our backend implementation into a bunch of microservices. Each microservice comes with...

Smoke tests

Smoke tests or build acceptance tests constitute a special family of tests that are traditionally used as early sanity checks by QA teams.

The use of the word smoke alludes to the old adage that wherever there is smoke, there is also fire. These checks are explicitly designed to identify early warning signals that something is wrong. It goes without saying that any issue uncovered by a smoke test is treated by the QA team as a show-stopper; if smoke tests fail, no further testing is performed. The QA team reports its findings to the development team and waits for a revised release candidate to be submitted for testing.

Once the smoke tests successfully pass, the QA team proceeds to run their suite of functional tests before giving the green light for release. The following diagram summarizes the process of running smoke tests for QA purposes:

Figure 5: Running smoke...

Chaos testing – breaking your systems in fun and interesting ways!

Let me begin this section with a question! How confident are you about the quality of your current software stack? If your answer happens to be something along the lines of, I don't really know until I make it fail, then we are in total agreement! If not, let me introduce you to the concept of chaos testing.

Chaos testing is a term that was initially coined by the engineering team at Netflix. The key point behind chaos testing is to evaluate your system's behavior when various components exhibit different types of failure. So, what kinds of failure are we talking about here? Here are a few interesting examples, ordered by their relative severity (low to high):

  • A service fails to reach another service it depends on
  • Calls between services exhibit high latency/jitter
  • Network links experience packet...

Tips and tricks for writing tests

In this section, I will be going through some interesting ideas that can help super-charge your daily test workflow. What's more, we will also be exploring some neat tricks that you can use to isolate tests, mock calls to system binaries, and control time within your tests.

Using environment variables to set up or skip tests

In a project of any size, you are eventually bound to come across a series of tests that depend on external resources that are created or configured in an ad hoc fashion.

A typical example of such a use case would be a test suite that talks to a database. As the engineers working locally on the code base, we would probably spin up a local database instance with a...

Summary

As the old proverb goes: you cannot build a house without good foundations. The same principle also applies to software engineering. Having a solid test infrastructure in place goes a long way to allowing engineers to work on new features while being confident that their changes will not break the existing code.

Through the course of this chapter, we performed a deep dive into the different types of testing that you need to be aware of when working on medium- to large-scale systems. To begin with, we discussed the concept of unit testing, the essential must-have type of test for all projects, regardless of size, whose primary role is to ensure that individual units of code work as expected in isolation. Then, we tackled more complex patterns, such as integration and functional testing, which verify that units and, by extension, the complete system work harmoniously together...

Questions

  1. What is the difference between a stub and a mock?
  2. Explain how fake objects work and describe an example scenario where you would opt to use a fake object instead of a mock.
  3. What are the main components of a table-driven test?
  4. What is the difference between a unit test and an integration test?
  5. What is the difference between an integration test and a functional test?
  6. Describe the ambassador pattern and how it can be exploited to safely run tests in production.

Further reading

  1. Bash manual: here documents: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Here-Documents.
  2. clockwork: A fake clock for golang: https://github.com/jonboulle/clockwork.
  3. gocheck: Rich testing for the Go language: http://labix.org/gocheck.
  4. gomock: A mocking framework for the Go programming language: https://github.com/golang/mock.
  5. Meszaros, Gerard: XUnit Test Patterns: Refactoring Test Code. Upper Saddle River, NJ, USA : Prentice Hall PTR, 2006 ISBN 0131495054 (https://www.worldcat.org/title/xunit-test-patterns-refactoring-test-code/oclc/935197390).
  6. Selenium: Browser automation: https://www.seleniumhq.org.
  7. testify: A toolkit with common assertions and mocks that plays nicely with the standard library: https://github.com/stretchr/testify.
  8. juju/clock: Clock definition and a testing clock: https://github.com/juju/clock.
...
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Hands-On Software Engineering with Golang
Published in: Jan 2020Publisher: PacktISBN-13: 9781838554491
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Achilleas Anagnostopoulos

Achilleas Anagnostopoulos has been writing code in a multitude of programming languages since the mid 90s. His main interest lies in building scalable, microservice-based distributed systems where components are interconnected via gRPC or message queues. Achilleas has over 4 years of experience building production-grade systems using Go and occasionally enjoys pushing the language to its limits through his experimental gopher-os project: a 64-bit kernel written entirely in Go. He is currently a member of the Juju team at Canonical, contributing to one of the largest open source Go code bases in existence.
Read more about Achilleas Anagnostopoulos