Skip to content

Instantly share code, notes, and snippets.

@spilth
Last active August 6, 2018 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spilth/75b766958e7d8f9953002998c30ae21a to your computer and use it in GitHub Desktop.
Save spilth/75b766958e7d8f9953002998c30ae21a to your computer and use it in GitHub Desktop.
Outside In Web Development with Go

Outside In Web Development with Go

I'd like to build a simple web application in Go using Outside In Testing. This means starting by writing a test that pretends to be a user visiting the application and setting up expectations about what they should be seeing.

We'll be using the following:

  • Agouti - an acceptance testing framework
  • Gingko - a BDD-style testing framework
  • Gomega - a matcher/assertion library

Install Go

$ brew install golang
$ brew install phantomjs
$ export GOPATH="$HOME/go"
$ export GOBIN="$GOPATH/bin"
$ export PATH="$GOBIN:$PATH"

Create Your Project

$ mkdir -p ~/go/src/github.com/spilth/web-project
$ cd ~/go/src/github.com/spilth/web-project

Install Dependencies

$ go get github.com/sclevine/agouti
$ go get github.com/onsi/ginkgo/ginkgo
$ go get github.com/onsi/gomega

Generate a Test Suite Wrapper

We can use ginkgo to create a test suite wrapper:

$ ginkgo bootstrap --agouti

Edit web_project_suite_test.go and choose the web driver you want to use:

package web_project_test

import (
	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sclevine/agouti"
)

func TestWebProject(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "WebProject Suite")
}

var agoutiDriver *agouti.WebDriver

var _ = BeforeSuite(func() {
	agoutiDriver = agouti.PhantomJS()

	Expect(agoutiDriver.Start()).To(Succeed())
})

var _ = AfterSuite(func() {
	Expect(agoutiDriver.Stop()).To(Succeed())
})

Then run this empty test suite with:

$ go test
Running Suite: WebProject Suite
===============================
Random Seed: 1533253105
Will run 0 of 0 specs


Ran 0 of 0 Specs in 2.587 seconds
SUCCESS! -- 0 Passed | 0 Failed | 0 Pending | 0 Skipped
PASS
ok  	<github.com/spilth/web-project>	2.603s

Generate a Feature Test

Now lets create an actual feature test that looks for something on the homepage.

$ ginkgo generate --agouti homepage

Edit homepage_test.go generated by the above command to contain the following:

package web_project_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sclevine/agouti"
		)

var _ = Describe("Homepage", func() {
	var page *agouti.Page

	BeforeEach(func() {
		var err error
		page, err = agoutiDriver.NewPage()
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		Expect(page.Destroy()).To(Succeed())
	})

	It("should show a welcome message", func() {
		By("showing it on the homepage", func() {
			Expect(page.Navigate("http://localhost:3000")).To(Succeed())
			Expect(page.HTML()).To(ContainSubstring("Hello, world!"))
		})
	})
})

This will fail because we haven't implemented anything and nothing is running on port 3000

Create the Web Server

Create server.go with the following code:

package web_project

import (
	"fmt"
	"net/http"
)

func Server() {
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		fmt.Fprint(writer, "Hello, world!")
	})

	http.ListenAndServe(":3000", nil)
}

This will still fail because the feature test doesn't know how to start up the web server.

Update the BeforeSuite Method

Edit web_project_test_suite.go and update the BeforeSuite method to spawn the web server:

package web_project_test

import (
	"testing"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sclevine/agouti"
	"github.com/spilth/web-project"
)

func TestWebProject(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "WebProject Suite")
}

var agoutiDriver *agouti.WebDriver

var _ = BeforeSuite(func() {
	go web_project.Server()

	agoutiDriver = agouti.PhantomJS()

	Expect(agoutiDriver.Start()).To(Succeed())
})

var _ = AfterSuite(func() {
	Expect(agoutiDriver.Stop()).To(Succeed())
})

Now when you run go test your test should pass!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment