In this video, we’re going to be exploring the wonderful world of test fixtures and how you can incorporate them into your Go tests and gain fame and fortune!
What Are Test Fixtures?
This was a new term for me when I started developing Go applications. I wasn’t entirely sure what it meant, but on further research it seems that test fixtures are effectively files which store some form of state that we need for our tests to run.
In this example, our tests fixtures will be some yaml
files that we’ll be referencing in our tests to ensure that our tests run in a repeatable and stable environment.
A Test’s Working Directory
These test fixtures that we’ll be creating are going to live in a special testdata
directory within each of our packages.
Now, when we call the go test
command, it is going to automatically loop through all of the packages within our project. For each package, it will set the current working directory to the package’s root directory and then execute all tests which follow the form TestXxx(t *testing.T)
.
An Example
Now that the theory is out of the way, let’s dive into the code and start implementing some tests that will utilize this concept.
Let’s mix things up a bit and create a new directory called yamltohtml
which will feature a yamltohtml.go
and a yamltohtml_test.go
file. This package will be tasked with reading in Yaml files and converting them to HTML
files for us.
Let’s start off by validating this working directory concept for our tests by creating a TestPWD
test:
package Yaml_test
import (
"os"
"testing"
)
func TestPWD(t *testing.T) {
workingDir, err := os.Getwd()
if err != nil {
t.Fail()
}
t.Log(workingDir)
}
When we go to run this with the verbose flag, we should see that it’s printing out the absolute path to our yamltohtml
package directory:
$ go test ./... -v
...
=== RUN TestPWD
Yaml_test.go:13: /Users/elliot/Documents/Projects/TutorialEdge/courses/go-testing-bible/yamltohtml
Implementing a YamlToHTML function
Let’s implement the function that will take our Yaml files and spit out a string containing the generated HTML:
package yamltohtml
import (
"bytes"
"html/template"
"io/ioutil"
"gopkg.in/yaml.v2"
)
type PageData struct {
Title string `yaml:"Title"`
Desc string `yaml:"Desc"`
Body string `yaml:"Body"`
}
func YamlToHTML(path string) (string, error) {
tmpl, err := template.New("page").Parse(`<html><head><title>{{.Title}}</title></head><body>{{.Body}}</body></html>`)
if err != nil {
return "", err
}
data, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
var pageData PageData
err = yaml.Unmarshal(data, &pageData)
if err != nil {
return "", err
}
var tpl bytes.Buffer
if err := tmpl.Execute(&tpl, pageData); err != nil {
return "", err
}
return tpl.String(), nil
}
Now that we have our new function in place, let’s set about trying to test this. In order to do this, we’ll need to set up a few text fixtures.
The Testdata Directory
Now, within the yamltohtml
package directory, let’s create a new directory called testdata
which will host the files we’ll be using to test our new function.
Within this directory, let’s create a new yaml
file called test_01.yml
:
---
Title: "My Awesome Page"
Desc: "My description"
Body: |
This is my awesome body
Now, let’s try and create a test that will read this test_01.yml
file and convert it to a HTML
string.
package yamltohtml_test
import (
"testing"
"github.com/TutorialEdge/go-testing-bible/yamltohtml"
)
type TestCase struct {
desc string
path string
expected string
}
func TestYamlToHTML(t *testing.T) {
testCases := []TestCase{
TestCase{
desc: "Tests title is set properly",
path: "testdata/test_01.yml",
expected: "<html><head><title>My Awesome Page</title></head><body>This is my awesome body</body></html>",
},
TestCase{
desc: "Tests body is set properly",
path: "testdata/test_02.yml",
expected: "<html><head><title>My Second Page</title></head><body>This is my awesome body</body></html>",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
result, err := yamltohtml.YamlToHTML(test.path)
if err != nil {
t.Fail()
}
t.Log(result)
if result != test.expected {
t.Fail()
}
})
}
}
Perfect, with this in place, our tests should successfully reference the 2 test yaml files we have created that live within the testdata
directory.
Conclusion
Awesome, so in this tutorial, we looked at the concept of test fixtures within the testdata
directory and how you could reference these test fixtures within your own Go tests.
In the next video in this course, we’ll be looking at how you can effectively create a suite of benchmarks so that you can better understand the performance of your code and how it handles a huge number of calls per second.