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
$ brew install golang
$ brew install phantomjs
$ export GOPATH="$HOME/go"
$ export GOBIN="$GOPATH/bin"
$ export PATH="$GOBIN:$PATH"
$ mkdir -p ~/go/src/github.com/spilth/web-project
$ cd ~/go/src/github.com/spilth/web-project
$ go get github.com/sclevine/agouti
$ go get github.com/onsi/ginkgo/ginkgo
$ go get github.com/onsi/gomega
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
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 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.
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!