Video:

Acceptance Tests with Resty

February 21, 2021

Course Instructor: Elliot Forbes

Hey Gophers! My name is Elliot and I'm the creator of TutorialEdge and I've been working with Go systems for roughly 5 years now.

How can we guarantee our application is working as we intend it to? And how do we ensure that when we are making changes to our application, we aren’t somehow breaking other systems that rely upon our service? This is where acceptance tests come in to play.

Acceptance tests allow us to automatically test our services from the perspective of an upstream client and are a brilliant way to help guard against some potential regressions within our system over time.

In this video, we are going to take a look at how we can implement acceptance tests for our REST API using resty!

Getting Started

Let’s start off by creating a new directory within the root of our project called test/. This is going to house all of the acceptance or e2e tests for our API and the reason it’s in a separate test directory is that we don’t necessarily want it knowing any of the implementation details for our API. We effectively want it to test our application and treat it as a black box in a similar fashion to how our clients would treat the API.

Within this test directory, let’s create a new file called health_test.go file, and within this file we are going to create a simple test for our health check endpoint.

test/health_test.go
// +build e2e

package test

import (
    "fmt"
    "testing"

    "github.com/go-resty/resty/v2"
    "github.com/stretchr/testify/assert"
)

func TestHealthEndpoint(t *testing.T) {
    fmt.Println("running e2e test for health check endpoint")

    client := resty.New()
    resp, err := client.R().Get("http://localhost:8080/api/health")
    if err != nil {
        t.Fail()
    }
    assert.Equal(t, 200, resp.StatusCode())
}

With this in place, let’s attempt to run this now:

$ go test ./... -tags=e2e -v

Build Tags

By using build tags, we are effectively filtering out all of the tests that we don’t want to run within our project. In this case, we’ve added the e2e build tag to the top of our health_test.go file and as we expand our e2e tests, we’ll want to add this same build tag to the top of all our additional files and then we can run them all together using this -tags=e2e flag on the go test command.

Testing Comment Endpoints

Now this pattern that we’ve used above is going to be the same pattern we are going to use to test all of our comment endpoints.

Let’s create a new file that is going to house our e2e tests for the comment endpoints now called comment_test.go:

test/comment_test.go
// +build e2e

package test

import (
	"testing"

	"github.com/go-resty/resty/v2"
	"github.com/stretchr/testify/assert"
)

func TestGetComments(t *testing.T) {
	client := resty.New()
	resp, err := client.R().Get(BASE_URL + "/api/comment")
	if err != nil {
		t.Fail()
	}

	assert.Equal(t, 200, resp.StatusCode())
}

func TestPostComment(t *testing.T) {
	client := resty.New()
	resp, err := client.R().
		SetBody(`{"slug": "/", "author": "12345", "body": "hello world"}`).
		Post(BASE_URL + "/api/comment")
	assert.NoError(t, err)

	assert.Equal(t, 200, resp.StatusCode())
}

We’ll also want to create a test/config.go file in which we’ll use to house any configuration that will be used across our e2e tests:

test/config.go
// +build e2e

package test

const (
	BASE_URL = "http://localhost:8080"
)

With this in place, let’s attempt to run this now:

$ go test ./... -tags=e2e -v

We should see that all of our E2E tests now run against our API and the assertions we have made pass. We haven’t covered implemented the tests for every endpoint, however I’m leaving this as an exercise for the viewer.

Conclusion

Awesome, so in this tutorial, we have successfully set up an acceptance test suite that queries our API and ensures that it is returning what we expect it to return.