Skip to content

Commit

Permalink
Merge pull request #281 from snikch/go-documentation
Browse files Browse the repository at this point in the history
Add Go documentation
  • Loading branch information
Adam Kliment committed Nov 20, 2015
2 parents 54b053b + 9d9e7fb commit e96483b
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 0 deletions.
205 changes: 205 additions & 0 deletions docs/hooks-go.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Writing Dredd Hooks In Go

[![Godoc Reference](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](https://godoc.org/github.com/snikch/goodman)

[GitHub repository](https://github.com/snikch/goodman)

Go hooks are using [Dredd's hooks handler socket interface](hooks-new-language.md). For using Go hooks in Dredd you have to have [Dredd already installed](quickstart.md). The Go library is called `goodman`.

## Installation

```
$ go get github.com/snikch/goodman
```

## Usage

Using Dredd with Go is slightly different to other languages, as a binary needs to be compiled for execution. Instead of providing a variety of hookfiles to run, your own binary is built using the Go hooks library `goodman` to run your specific hooks. The path to this binary is passed to dredd via the `--language` flag. You may also need to supply a `--hookfiles` flag to get the tests to run, but the value of this is of no matter (the dredd runner requires it).

```
$ dredd apiary.apib http://localhost:3000 --language ./my-dredd-hook-server --hookfiles *.go
```

## API Reference

You’ll need to know about three things to get your own hook handler up and running.

1. A `Runner` is a type that you can define event callbacks on, such as `beforeEach`, `afterAll` etc.

2. Callbacks receive a `Transaction` instance, or an array of them

3. A `Server` will run your `Runner` and handle receiving events on the dredd socket.

### Runner Callback Events

The `Runner` type has the following callback methods.

1. `BeforeEach`, `BeforeEachValidation`, `AfterEach`
- accepts a function as a first argument passing a [Transaction object](hooks.md#transaction-object-structure) as a first argument

2. `Before`, `BeforeValidation`, `After`
- accepts [transaction name](hooks.md#getting-transaction-names) as a first argument
- accepts a function as a second argument passing a [Transaction object](hooks.md#transaction-object-structure) as a first argument of it

3. `BeforeAll`, `AfterAll`
- accepts a function as a first argument passing a Slice of [Transaction objects](hooks.md#transaction-object-structure) as a first argument

Refer to [Dredd execution lifecycle](usage.md#dredd-execution-lifecycle) to find when each hook callback is executed.

### Using the Go API

Example usage of all methods.

```go
package main

import (
"fmt"
"log"

"github.com/snikch/goodman"
)

func main() {
server := goodman.NewServer(NewRunner())
log.Fatal(server.Run())
}

func NewRunner() *goodman.Runner {
runner := goodman.NewRunner()
runner.BeforeAll(func(t []*goodman.Transaction) {
fmt.Println("before all")
})
runner.BeforeEach(func(t *goodman.Transaction) {
fmt.Println("before each")
})
runner.Before("/message > GET", func(t *goodman.Transaction) {
fmt.Println("before /message > GET")
})
runner.BeforeEachValidation(func(t *goodman.Transaction) {
fmt.Println("before each validation")
})
runner.BeforeValidation("/message > GET", func(t *goodman.Transaction) {
fmt.Println("before validation of /message > GET")
})
runner.After("/message > GET", func(t *goodman.Transaction) {
fmt.Println("after")
})
runner.AfterEach(func(t *goodman.Transaction) {
fmt.Println("after each")
})
runner.AfterAll(func(t []*goodman.Transaction) {
fmt.Println("after all")
})
return runner
}
```

## Examples

### How to Skip Tests

Any test step can be skipped by setting the `Skip` property of the `Transaction` instance to `true`.

```go
package main

import (
"fmt"
"log"

"github.com/snikch/goodman"
)

func main() {
runner := goodman.NewRunner()
runner.Before("Machines > Machines collection > Get Machines", func(t *goodman.Transaction) {
t.Skip = true
})
server := goodman.NewServer(runner)
log.Fatal(server.Run())
}
```

### Failing Tests Programmatically

You can fail any step by setting the `Fail` field of the `Transaction` instance to `true` or any string with a descriptive message.

```go
package main

import (
"fmt"
"log"

"github.com/snikch/goodman"
)

func main() {
runner := goodman.NewRunner()
runner.Before("Machines > Machines collection > Get Machines", func(t *goodman.Transaction) {
t.Fail = true
})
runner.Before("Machines > Machines collection > Post Machines", func(t *goodman.Transaction) {
t.Fail = "POST is broken"
})
server := goodman.NewServer(runner)
log.Fatal(server.Run())
}
```

### Modifying the Request Body Prior to Execution

```go
package main

import (
"fmt"
"log"

"github.com/snikch/goodman"
)

func main() {
runner := goodman.NewRunner()
runner.Before("Machines > Machines collection > Get Machines", func(t *goodman.Transaction) {
body := map[string]interface{}{}
json.Unmarshal([]byte(t.Request.Body), &body)

body["someKey"] = "new value"

newBody, _ := json.Marshal(body)
t.Request.body = string(newBody)
})
server := goodman.NewServer(runner)
log.Fatal(server.Run())
}
```

### Adding or Changing URI Query Parameters for All Requests

```go
package main

import (
"fmt"
"log"

"github.com/snikch/goodman"
)

func main() {
runner := goodman.NewRunner()
runner.BeforeEach(func(t *goodman.Transaction) {
paramToAdd = "some=param";

if strings.Contains(t.FullPath, "?") {
t.FullPath += "&" + paramToAdd
} else {
t.FullPath += "?" + paramToAdd
}
})
server := goodman.NewServer(runner)
log.Fatal(server.Run())
}
```
1 change: 1 addition & 0 deletions docs/hooks-new-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ Dredd hooks language abstraction bridge comes with [the language agnostic test s
If you have any questions, please:

- Have a look at the [Ruby](https://github.com/apiaryio/dredd-hooks-ruby), [Python](https://github.com/apiaryio/dredd-hooks-python), and [PHP](https://github.com/ddelnano/dredd-hooks-php) hook handlers codebase for inspiration
- If you’re writing a hook handler for a compiled language, check out the [Go](https://github.com/snikch/goodman) implementation
- File an [issue in Dredd repository](https://github.com/apiaryio/dredd/issues/new)
1 change: 1 addition & 0 deletions docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You can interact with your server implementation in following languages:
- [Python](hooks-python.md)
- [Node.js](hooks-nodejs.md)
- [PHP](hooks-php.md)
- [Go](hooks-go.md)
- [Sandboxed JavaScript](hooks-js-sandbox.md)

Dredd doesn't speak your language? [**It's very easy to write support for your language.**](hooks-new-language.md) Your contribution is more than welcome!
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Dredd supports writing [hooks](hooks.md) glue code for testing stateful servers,
- [Python](hooks-python.md)
- [Node.js](hooks-nodejs.md)
- [PHP](hooks-php.md)
- [Go](hooks-go.md)
- [*Add your language here*](hooks-new-language.md)

## Documentation Reference
Expand Down

0 comments on commit e96483b

Please sign in to comment.