Testing With Ginkgo and Gomega

A simple guide of how to start your testing using Ginkgo and Gomega with real examples

Denis Peganov
8 min readMar 2, 2023
Source: https://github.com/marcusolsson/gophers/blob/master/orbiter-gopher.png

In this tutorial we’ll cover the basic structure of a Ginkgo and Gomega, and create your own tests using Ginkgo framework.
By the end of this tutorial, you’ll have a solid understanding of how to write tests using Ginkgo and Gomega. Furthermore, you’ll be able to apply this knowledge to your own Go projects. Let’s get started!

Table of contents

What is Ginkgo
What is Gomega
Ginkgo framework implementation
Create a new Go project
Set up a new Ginkgo test suite
Download libraries
Determine the service under test
Add testcases (specs)
Run your tests

What is Ginkgo

Ginkgo is a testing framework for Go programming language, which is designed to facilitate writing behavior-driven (BDD) tests. It provides a simple and intuitive syntax for writing test suites, cases and assertions, making it easier to write, read and maintain tests.

One of the main benefits of Ginkgo is that it provides an expressive and flexible way to write tests that can be easily understood by both technical and non-technical team members. It uses a natural language format that allows developers to write tests in a way that closely resembles the way users interact with the system. This makes it easier to understand and maintain tests, and also helps ensure that the tests are aligned with the expected behavior of the system.

An example of BDD test written using Ginkgo:

Describe("Simple service test", func() {
Context("When receiving a valid request", func() {
It("should return the correct response", func() {
// some request preparation here
response, err := client.Do(request)
})
})
})

Ginkgo also provides a rich set of features for test organization, such as parallel test execution, test output formatting and test isolation. This makes it easier to manage large test suites and also helps reduce the time it takes to run tests.

In the context of microservices testing, Ginkgo is particularly well-suited for testing individual services as well as the interactions between them. It provides a flexible and expressive syntax for testing both positive and negative scenarios, such as testing the behavior of the service when receiving invalid inputs or testing the resilience of the service to network failures.

What is Gomega

Gomega is a matcher/assertion library. It is best paired with the Ginkgo BDD test framework, but can be adapted for use in other contexts too.
Gomega provides a rich set of matchers that allow you to easily and expressively test your code for various conditions and outcomes.

Matchers in Gomega are functions that return a boolean value indicating whether a given assertion is true or false. For example, the Equal matcher checks whether two values are equal, and returns true if they are, and false if they are not.

Ginkgo and Gomega are two Go testing libraries that are often used together to provide a powerful and expressive testing framework. Here are some reasons why it’s better to use Ginkgo with Gomega:

  1. Readability.
    Gomega provides a very readable syntax for your tests. The fluent API provided by Gomega allows you to write assertions in a natural language style that is easy to read and understand.
  2. Simplicity.
    Gomega simplifies your test code by providing a rich set of matchers that can test for a wide range of conditions. This reduces the amount of code you need to write, making your tests more readable and easier to maintain.
  3. Modularity.
    Gomega is modular, meaning that you can use only the matchers that you need for a particular test case. This can help to keep your test code lean and reduce unnecessary complexity.
  4. Integration with Ginkgo.
    Gomega is designed to integrate with Ginkgo, providing seamless support for Ginkgo’s BDD-style syntax. This allows you to write tests that are both expressive and easy to read.

Let’s add Gomega matchers to above example of Ginkgo BDD test:

Describe("SImple service test", func() {
Context("When receiving a valid request", func() {
It("should return the correct response", func() {
// some request preparation here
response, err := client.Do(request)
Expect(err).NotTo(HaveOccurred())
Expect(response.StatusCode).To(Equal(http.StatusOK))

responseBody, _ := ioutil.ReadAll(response.Body)
Expect(string(responseBody)).To(Equal(expectedResponse))
})
})
})

As you can see now, Ginkgo and Gomega together provide a powerful and expressive testing framework for your Go code. Gomega’s rich set of matchers and readable syntax make it a great choice for testing with Ginkgo, and can help to simplify your test code while making it more expressive and easier to read.

Ginkgo framework implementation

Now let’s make our hands dirty and implement your own Ginkgo framework!

Prerequisities:

Create a new Go project

Let’s start with opening GoLang IDE and creating a new Go project.
This procedure is intuitive simple, but just in case, do the following steps in your GoLang IDE:
FileNewProjectCreate

Set up a new Ginkgo test suite

Run ginkgo bootstrap command in your project’s directory to quickly and easily set up a new Ginkgo test suite.

This command also creates the necessary file structure and configuration files needed to get started with Ginkgo testing. Created by that command *_suite_test.go file also contains necessary imports and package declarations.

Go code is organized into modules. A module is usually associated with a repository and consists of a series of versioned packages. Most of the times each package is associated with a single directory within the module’s file tree containing a series of source code files. When testing Go code, unit tests for a package resides within the same directory as the package and are named *_test.go. And Ginkgo follows this convention, as you probably already noticed.

Download libraries

Download needed libraries using the following commands:

  1. go get github.com/onsi/ginkgo/v2@v2.8.3 (replace the number of version with the latest one, which you can find here)
  2. go get github.com/onsi/gomega/...

The go get command is used in Go to download and install packages and their dependencies from remote repositories. When you run go get, it will download the package source code from the specified repository (usually from Git). If the package has dependencies, that command will also download and install those dependencies.

With the go get command you also can:

  • Update a package: go get -u github.com/user/repo will update the package to the latest version.
  • Install a specific version of a package: go get -u github.com/user/repo@v.1.2.3 will download and install version 1.2.3 of the package.
  • Install a package from a specific branch or tag: go get -u github.com/user/repo@mybranch will download and install the version of the package at the mybranch branch.
  • Install a package to a specific directory: go get -d github.com/user/repo will download the package source code but not install it, you can install it later using go install command.

Note that go get only works with packages that are hosted on a remote repository and have a go.mod file. For packages that are not hosted on a repository or do not use modules, you will need to manually download and install the package source code.

Determine the service under test

You can skip that step if you already have service which you will be testing and you just need a real example of implemented Ginkgo tests

To make the most of this article, you will need a running API-service to validate it using your Ginkgo tests. You can get that service just in seconds by looking into one of my previous posts. I promise it’s very easy and won’t take much time.

Once you have your local running API-service, you are ready to move into the next step.

Add testcases (specs)

In Ginkgo, specs are the individual test cases that make up a test suite. A spec typically consists of a description of the behavior being tested, followed by the actual test code.

Specs are defined using the It function, which takes a description string and a test function. The description string should describe the behavior being tested in a clear and concise way.

You can add all your specs directly into *_suite_test.go, but I recommend you to place your specs in separate files. This practice will make your testing life easier if you have packages with multiple files that need to be tested.

At this point, run a ginkgo generate cars command, where cars is the service which you will be testing. This way you will generate a test file named cars_test.go

Now, paste the following code, which I’ve already prepared for you, into your created cars_test.go file. But don’t forget to update the package name.

Using above tests you will validate that your local running service returns the correct response when you create a new car in it, and provides you an error message when you send some invalid request.
However, I believe it was quite easy for you to understand above tests right after you looked into them, since Ginkgo test may consist of many components which helps you to make it more understandable, and in this tutorial we are using the main three of them: Describe, Context and It.

  • Describe
    This is the top-level component of a Ginkgo test suite, and is used to group together a set of related tests. A Describe block typically describes a specific aspect of the system being tested, such as a package or module.
  • Context
    Within a Describe block, you can use context blocks to further group related tests together. A Context block typically describes a specific set of conditions or inputs for the tests being run.
  • It
    Finally, within a Context block, you can define individual test cases using It blocks. An It block describes a specific behavior or feature of the system being tested and contains the actual test code.

By organizing your tests in such way, you can create well-structured and easily readable test suites that make it clear what behavior is being tested and under what conditions.

Run your tests

To run your tests, simply run the ginkgo command inside your project’s directory.

Ginkgo will output the test results to the console:

If you want to save the output to a file, you can use the -r flag followed by the path to the output file: ginkgo -r results.txt. This will save the test results to the results.txt file instead of printing them to the console.

Later, you can detefmine a specific test file or directory to run by passing it as an argument to the ginkgo command, ginkg my_test_file.go as an example. This command will run only the tests of my_test_file.go.

That’s it! 🎉
From here, you can continue to add more test cases and suites to your test suite as needed, and use the various features and options available in Ginkgo to write comprehensive and effective tests for your code. Good luck!

--

--

Denis Peganov

Hey, I'm a QA Engineer dedicated to ensuring the quality of multiple products, and I'm passionate about sharing my expertise and insights with the community.