Skip to content
Dom Del Nano edited this page Jun 5, 2016 · 9 revisions

The following is a sample Go web service that is tested with Dredd and goodman to help you understand how goodman can be used to help bootstrap your application. Specifically, it will be used to seed the web application's database before API endpoints that query the database are requested. This example will be using a sqlite database.

This example uses govendor, you must install this prior to running the example

##Important Details All files referenced in this section will assume the current working directory of $GOPATH/src/github.com/snikch/goodman/example.

The api.apib file

FORMAT: 1A

# My Api
## GET /message
+ Response 200 (text/html; charset=utf-8)
    + Body

            Hello World!

# Group Users

## Endpoint [/users/{id}]

+ Parameters
    - id: 1 - (number) - Unique identifier for a user

### Getting a single user [GET]

+ Response 200 (application/json)

    + Body

            {
                "Id": 1,
                "Name": "Dom",
                "Email": "[email protected]"
            }

The api blueprint file specifies two endpoints /message and /users/{id}. The /message endpoint is not very interesting but the /users/{id} endpoint in a typical application would query a database for a user with the id given in the URL. We will use the goodman hooks to seed the database prior to Dredd making a request to this endpoint.

The go app we are testing is in a single file in main.go

// main.go
package main

import (
	"database/sql"
	"encoding/json"
	"log"
	"net/http"

	_ "github.com/mattn/go-sqlite3"
)

type User struct {
	Id    int
	Name  string
	Email string
}

func main() {
	http.HandleFunc("/users/1", func(w http.ResponseWriter, r *http.Request) {
		db, err := sql.Open("sqlite3", "./foo.db")
		if err != nil {
			log.Fatal(err)
		}
		defer db.Close()
		rows, err := db.Query(`select id, name, email from users where id = ?;`, 1)

		if err != nil {
			panic(err)
		}

		var id int
		var name string
		var email string
		for rows.Next() {
			err = rows.Scan(&id, &name, &email)

			if err != nil {
				log.Fatal(err)
			}

		}
		user := &User{
			Id:    id,
			Name:  name,
			Email: email,
		}
		data, err := json.Marshal(user)
		if err != nil {
			panic("Marshaling failed with message " + err.Error())
		}
		w.Header().Add("Content-Type", "application/json")
		w.Write(data)
	})

	http.HandleFunc("/message", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		w.Write([]byte("Hello World!\n"))
	})

	err := http.ListenAndServe(":8080", nil) // set listen port
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

This go app is an http server that listens of port 8080 and has two endpoints registered: /message, and /users/1. As you can see from the code the users endpoint queries a sqlite database for a user with the id of 1. In order for this to succeed when Dredd is run we need to seed the database with a user before the test is run. This seeding is done in the following hookfile.

hooks/hooks.go

package main

import (
	"database/sql"
	"log"
	"os"

	_ "github.com/mattn/go-sqlite3"
	"github.com/snikch/goodman/hooks"
	trans "github.com/snikch/goodman/transaction"
)

var (
	db sql.DB
)

func main() {
	h := hooks.NewHooks()
	server := hooks.NewServer(h)

	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	h.BeforeAll(func(t []*trans.Transaction) {
		_, err = db.Exec(`create table users (id integer not null primary key, name text, email text);`)
		if err != nil {
			log.Fatal(err)
		}
	})
	h.Before("Users > Endpoint > Getting a single user", func(t *trans.Transaction) {
		_, err = db.Exec(`insert into users (id, name, email) values (1, 'Dom', '[email protected]');`)
		if err != nil {
			log.Fatal(err)
		}
	})
	h.AfterAll(func(t []*trans.Transaction) {
		os.Remove("./foo.db")
	})
	server.Serve()
	defer server.Listener.Close()
}

As you can see in this file, it opens a sqlite database, creates a users table, and before the Users > Endpoint > Getting a single user transaction, seeds a user with an id of 1 into the database. Dredd will tell goodman when the transaction is about to happen and the hook callback will be executed so that when the /users/1 endpoint is requested the necessary data exist in the database.

##Running the example

  1. Install the command if you haven't already, instructions can be found here

  2. Move to example directory

cd $GOPATH/src/github.com/snikch/goodman/example
  1. Install dredd through package.json provided
# Make sure cwd is $GOPATH/src/github.com/snikch/goodman/example
npm install
  1. Install vendor'ed libraries through govendor
# Make sure cwd is $GOPATH/src/github.com/snikch/goodman/example
$GOPATH/bin/govendor sync
  1. Run dredd with the provided Makefile make dredd
  • The Makefile (and dredd target) is provided to compile both the hooks/hooks.go and main.go files and then run dredd. This is so that the necessary steps can be executed in a single command. Please see the Makefile for more details.
Clone this wiki locally