Browse Source

Vendor goblin

pull/46/head
Jacob McCann 8 years ago
parent
commit
8ab151197f
  1. 19
      vendor/github.com/franela/goblin/LICENSE
  2. 3
      vendor/github.com/franela/goblin/Makefile
  3. 141
      vendor/github.com/franela/goblin/README.md
  4. 59
      vendor/github.com/franela/goblin/assertions.go
  5. 36
      vendor/github.com/franela/goblin/go.snippets
  6. 302
      vendor/github.com/franela/goblin/goblin.go
  7. BIN
      vendor/github.com/franela/goblin/goblin_logo.jpg
  8. BIN
      vendor/github.com/franela/goblin/goblin_output.png
  9. 26
      vendor/github.com/franela/goblin/mono_reporter.go
  10. 137
      vendor/github.com/franela/goblin/reporting.go
  11. 21
      vendor/github.com/franela/goblin/resolver.go
  12. 8
      vendor/vendor.json

19
vendor/github.com/franela/goblin/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2013 Marcos Lilljedahl and Jonathan Leibiusky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

3
vendor/github.com/franela/goblin/Makefile

@ -0,0 +1,3 @@
export GOPATH=$(shell pwd)
test:
go test -v

141
vendor/github.com/franela/goblin/README.md

@ -0,0 +1,141 @@
[![Build Status](https://travis-ci.org/franela/goblin.png?branch=master)](https://travis-ci.org/franela/goblin)
Goblin
======
![](https://github.com/marcosnils/goblin/blob/master/goblin_logo.jpg?raw=true)
A [Mocha](http://mochajs.org/) like BDD testing framework for Go
No extensive documentation nor complicated steps to get it running
Run tests as usual with `go test`
Colorful reports and beautiful syntax
Why Goblin?
-----------
Inspired by the flexibility and simplicity of Node BDD and frustrated by the
rigorousness of Go way of testing, we wanted to bring a new tool to
write self-describing and comprehensive code.
What do I get with it?
----------------------
- Preserve the exact same syntax and behaviour as Node's Mocha
- Nest as many `Describe` and `It` blocks as you want
- Use `Before`, `BeforeEach`, `After` and `AfterEach` for setup and teardown your tests
- No need to remember confusing parameters in `Describe` and `It` blocks
- Use a declarative and expressive language to write your tests
- Plug different assertion libraries ([Gomega](https://github.com/onsi/gomega) supported so far)
- Skip your tests the same way as you would do in Mocha
- Automatic terminal support for colored outputs
- Two line setup is all you need to get up running
How do I use it?
----------------
Since ```go test``` is not currently extensive, you will have to hook Goblin to it. You do that by
adding a single test method in your test file. All your goblin tests will be implemented inside this function.
```go
package foobar
import (
"testing"
. "github.com/franela/goblin"
)
func Test(t *testing.T) {
g := Goblin(t)
g.Describe("Numbers", func() {
g.It("Should add two numbers ", func() {
g.Assert(1+1).Equal(2)
})
g.It("Should match equal numbers", func() {
g.Assert(2).Equal(4)
})
g.It("Should substract two numbers")
})
}
```
Ouput will be something like:
![](https://github.com/marcosnils/goblin/blob/master/goblin_output.png?raw=true)
Nice and easy, right?
Can I do asynchronous tests?
----------------------------
Yes! Goblin will help you to test asynchronous things, like goroutines, etc. You just need to add a ```done``` parameter to the handler function of your ```It```. This handler function should be called when your test passes.
```go
...
g.Describe("Numbers", func() {
g.It("Should add two numbers asynchronously", func(done Done) {
go func() {
g.Assert(1+1).Equal(2)
done()
}()
})
})
...
```
Goblin will wait for the ```done``` call, a ```Fail``` call or any false assertion.
How do I use it with Gomega?
----------------------------
Gomega is a nice assertion framework. But it doesn't provide a nice way to hook it to testing frameworks. It should just panic instead of requiring a fail function. There is an issue about that [here](https://github.com/onsi/gomega/issues/5).
While this is being discussed and hopefully fixed, the way to use Gomega with Goblin is:
```go
package foobar
import (
"testing"
. "github.com/franela/goblin"
. "github.com/onsi/gomega"
)
func Test(t *testing.T) {
g := Goblin(t)
//special hook for gomega
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })
g.Describe("lala", func() {
g.It("lslslslsls", func() {
Expect(1).To(Equal(10))
})
})
}
```
FAQ:
----
### How do I run specific tests?
If `-goblin.run=$REGES` is supplied to the `go test` command then only tests that match the supplied regex will run
TODO:
-----
We do have a couple of [issues](https://github.com/franela/goblin/issues) pending we'll be addressing soon. But feel free to
contribute and send us PRs (with tests please :smile:).
Contributions:
------------
Special thanks to [Leandro Reox](https://github.com/leandroreox) (Leitan) for the goblin logo.

59
vendor/github.com/franela/goblin/assertions.go

@ -0,0 +1,59 @@
package goblin
import (
"fmt"
"reflect"
"strings"
)
type Assertion struct {
src interface{}
fail func(interface{})
}
func objectsAreEqual(a, b interface{}) bool {
if reflect.TypeOf(a) != reflect.TypeOf(b) {
return false
}
if reflect.DeepEqual(a, b) {
return true
}
if fmt.Sprintf("%#v", a) == fmt.Sprintf("%#v", b) {
return true
}
return false
}
func formatMessages(messages ...string) string {
if len(messages) > 0 {
return ", " + strings.Join(messages, " ")
}
return ""
}
func (a *Assertion) Eql(dst interface{}) {
a.Equal(dst)
}
func (a *Assertion) Equal(dst interface{}) {
if !objectsAreEqual(a.src, dst) {
a.fail(fmt.Sprintf("%#v %s %#v", a.src, "does not equal", dst))
}
}
func (a *Assertion) IsTrue(messages ...string) {
if !objectsAreEqual(a.src, true) {
message := fmt.Sprintf("%v %s%s", a.src, "expected false to be truthy", formatMessages(messages...))
a.fail(message)
}
}
func (a *Assertion) IsFalse(messages ...string) {
if !objectsAreEqual(a.src, false) {
message := fmt.Sprintf("%v %s%s", a.src, "expected true to be falsey", formatMessages(messages...))
a.fail(message)
}
}

36
vendor/github.com/franela/goblin/go.snippets

@ -0,0 +1,36 @@
snippet gd
g.Describe("${1:name}", func() {
${2}
})
${0}
snippet git
g.It("${1:name}", func() {
${2}
})
${0}
snippet gait
g.It("${1:name}", func(done Done) {
done()
${2}
})
${0}
snippet gb
g.Before(func() {
${1}
})
${0}
snippet gbe
g.BeforeEach(func() {
${1}
})
${0}
snippet ga
g.After(func() {
${1}
})
${0}
snippet gae
g.AfterEach(func() {
${1}
})
${0}

302
vendor/github.com/franela/goblin/goblin.go

@ -0,0 +1,302 @@
package goblin
import (
"flag"
"fmt"
"regexp"
"runtime"
"sync"
"testing"
"time"
)
type Done func(error ...interface{})
type Runnable interface {
run(*G) bool
}
func (g *G) Describe(name string, h func()) {
d := &Describe{name: name, h: h, parent: g.parent}
if d.parent != nil {
d.parent.children = append(d.parent.children, Runnable(d))
}
g.parent = d
h()
g.parent = d.parent
if g.parent == nil && d.hasTests {
g.reporter.begin()
if d.run(g) {
g.t.Fail()
}
g.reporter.end()
}
}
func (g *G) Timeout(time time.Duration) {
g.timeout = time
g.timer.Reset(time)
}
type Describe struct {
name string
h func()
children []Runnable
befores []func()
afters []func()
afterEach []func()
beforeEach []func()
hasTests bool
parent *Describe
}
func (d *Describe) runBeforeEach() {
if d.parent != nil {
d.parent.runBeforeEach()
}
for _, b := range d.beforeEach {
b()
}
}
func (d *Describe) runAfterEach() {
if d.parent != nil {
d.parent.runAfterEach()
}
for _, a := range d.afterEach {
a()
}
}
func (d *Describe) run(g *G) bool {
failed := false
if d.hasTests {
g.reporter.beginDescribe(d.name)
for _, b := range d.befores {
b()
}
for _, r := range d.children {
if r.run(g) {
failed = true
}
}
for _, a := range d.afters {
a()
}
g.reporter.endDescribe()
}
return failed
}
type Failure struct {
stack []string
testName string
message string
}
type It struct {
h interface{}
name string
parent *Describe
failure *Failure
reporter Reporter
isAsync bool
}
func (it *It) run(g *G) bool {
g.currentIt = it
if it.h == nil {
g.reporter.itIsPending(it.name)
return false
}
//TODO: should handle errors for beforeEach
it.parent.runBeforeEach()
runIt(g, it.h)
it.parent.runAfterEach()
failed := false
if it.failure != nil {
failed = true
}
if failed {
g.reporter.itFailed(it.name)
g.reporter.failure(it.failure)
} else {
g.reporter.itPassed(it.name)
}
return failed
}
func (it *It) failed(msg string, stack []string) {
it.failure = &Failure{stack: stack, message: msg, testName: it.parent.name + " " + it.name}
}
func parseFlags() {
//Flag parsing
flag.Parse()
if *regexParam != "" {
runRegex = regexp.MustCompile(*regexParam)
} else {
runRegex = nil
}
}
var timeout = flag.Duration("goblin.timeout", 5*time.Second, "Sets default timeouts for all tests")
var isTty = flag.Bool("goblin.tty", true, "Sets the default output format (color / monochrome)")
var regexParam = flag.String("goblin.run", "", "Runs only tests which match the supplied regex")
var runRegex *regexp.Regexp
func init() {
parseFlags()
}
func Goblin(t *testing.T, arguments ...string) *G {
g := &G{t: t, timeout: *timeout}
var fancy TextFancier
if *isTty {
fancy = &TerminalFancier{}
} else {
fancy = &Monochrome{}
}
g.reporter = Reporter(&DetailedReporter{fancy: fancy})
return g
}
func runIt(g *G, h interface{}) {
defer timeTrack(time.Now(), g)
g.mutex.Lock()
g.timedOut = false
g.mutex.Unlock()
g.timer = time.NewTimer(g.timeout)
g.shouldContinue = make(chan bool)
if call, ok := h.(func()); ok {
// the test is synchronous
go func(c chan bool) { call(); c <- true }(g.shouldContinue)
} else if call, ok := h.(func(Done)); ok {
doneCalled := 0
go func(c chan bool) {
call(func(msg ...interface{}) {
if len(msg) > 0 {
g.Fail(msg)
} else {
doneCalled++
if doneCalled > 1 {
g.Fail("Done called multiple times")
}
c <- true
}
})
}(g.shouldContinue)
} else {
panic("Not implemented.")
}
select {
case <-g.shouldContinue:
case <-g.timer.C:
//Set to nil as it shouldn't continue
g.shouldContinue = nil
g.timedOut = true
g.Fail("Test exceeded " + fmt.Sprintf("%s", g.timeout))
}
// Reset timeout value
g.timeout = *timeout
}
type G struct {
t *testing.T
parent *Describe
currentIt *It
timeout time.Duration
reporter Reporter
timedOut bool
shouldContinue chan bool
mutex sync.Mutex
timer *time.Timer
}
func (g *G) SetReporter(r Reporter) {
g.reporter = r
}
func (g *G) It(name string, h ...interface{}) {
if matchesRegex(name) {
it := &It{name: name, parent: g.parent, reporter: g.reporter}
notifyParents(g.parent)
if len(h) > 0 {
it.h = h[0]
}
g.parent.children = append(g.parent.children, Runnable(it))
}
}
func matchesRegex(value string) bool {
if runRegex != nil {
return runRegex.MatchString(value)
}
return true
}
func notifyParents(d *Describe) {
d.hasTests = true
if d.parent != nil {
notifyParents(d.parent)
}
}
func (g *G) Before(h func()) {
g.parent.befores = append(g.parent.befores, h)
}
func (g *G) BeforeEach(h func()) {
g.parent.beforeEach = append(g.parent.beforeEach, h)
}
func (g *G) After(h func()) {
g.parent.afters = append(g.parent.afters, h)
}
func (g *G) AfterEach(h func()) {
g.parent.afterEach = append(g.parent.afterEach, h)
}
func (g *G) Assert(src interface{}) *Assertion {
return &Assertion{src: src, fail: g.Fail}
}
func timeTrack(start time.Time, g *G) {
g.reporter.itTook(time.Since(start))
}
func (g *G) Fail(error interface{}) {
//Skips 7 stacks due to the functions between the stack and the test
stack := ResolveStack(7)
message := fmt.Sprintf("%v", error)
g.currentIt.failed(message, stack)
if g.shouldContinue != nil {
g.shouldContinue <- true
}
g.mutex.Lock()
defer g.mutex.Unlock()
if !g.timedOut {
//Stop test function execution
runtime.Goexit()
}
}

BIN
vendor/github.com/franela/goblin/goblin_logo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
vendor/github.com/franela/goblin/goblin_output.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

26
vendor/github.com/franela/goblin/mono_reporter.go

@ -0,0 +1,26 @@
package goblin
import ()
type Monochrome struct {
}
func (self *Monochrome) Red(text string) string {
return "!" + text
}
func (self *Monochrome) Gray(text string) string {
return text
}
func (self *Monochrome) Cyan(text string) string {
return text
}
func (self *Monochrome) WithCheck(text string) string {
return ">>>" + text
}
func (self *Monochrome) Green(text string) string {
return text
}

137
vendor/github.com/franela/goblin/reporting.go

@ -0,0 +1,137 @@
package goblin
import (
"fmt"
"strconv"
"strings"
"time"
)
type Reporter interface {
beginDescribe(string)
endDescribe()
begin()
end()
failure(*Failure)
itTook(time.Duration)
itFailed(string)
itPassed(string)
itIsPending(string)
}
type TextFancier interface {
Red(text string) string
Gray(text string) string
Cyan(text string) string
Green(text string) string
WithCheck(text string) string
}
type DetailedReporter struct {
level, failed, passed, pending int
failures []*Failure
executionTime, totalExecutionTime time.Duration
fancy TextFancier
}
func (r *DetailedReporter) SetTextFancier(f TextFancier) {
r.fancy = f
}
type TerminalFancier struct {
}
func (self *TerminalFancier) Red(text string) string {
return "\033[31m" + text + "\033[0m"
}
func (self *TerminalFancier) Gray(text string) string {
return "\033[90m" + text + "\033[0m"
}
func (self *TerminalFancier) Cyan(text string) string {
return "\033[36m" + text + "\033[0m"
}
func (self *TerminalFancier) Green(text string) string {
return "\033[32m" + text + "\033[0m"
}
func (self *TerminalFancier) WithCheck(text string) string {
return "\033[32m\u2713\033[0m " + text
}
func (r *DetailedReporter) getSpace() string {
return strings.Repeat(" ", (r.level+1)*2)
}
func (r *DetailedReporter) failure(failure *Failure) {
r.failures = append(r.failures, failure)
}
func (r *DetailedReporter) print(text string) {
fmt.Printf("%v%v\n", r.getSpace(), text)
}
func (r *DetailedReporter) printWithCheck(text string) {
fmt.Printf("%v%v\n", r.getSpace(), r.fancy.WithCheck(text))
}
func (r *DetailedReporter) beginDescribe(name string) {
fmt.Println("")
r.print(name)
r.level++
}
func (r *DetailedReporter) endDescribe() {
r.level--
}
func (r *DetailedReporter) itTook(duration time.Duration) {
r.executionTime = duration
r.totalExecutionTime += duration
}
func (r *DetailedReporter) itFailed(name string) {
r.failed++
r.print(r.fancy.Red(strconv.Itoa(r.failed) + ") " + name))
}
func (r *DetailedReporter) itPassed(name string) {
r.passed++
r.printWithCheck(r.fancy.Gray(name))
}
func (r *DetailedReporter) itIsPending(name string) {
r.pending++
r.print(r.fancy.Cyan("- " + name))
}
func (r *DetailedReporter) begin() {
}
func (r *DetailedReporter) end() {
comp := fmt.Sprintf("%d tests complete", r.passed)
t := fmt.Sprintf("(%d ms)", r.totalExecutionTime/time.Millisecond)
//fmt.Printf("\n\n \033[32m%d tests complete\033[0m \033[90m(%d ms)\033[0m\n", r.passed, r.totalExecutionTime/time.Millisecond)
fmt.Printf("\n\n %v %v\n", r.fancy.Green(comp), r.fancy.Gray(t))
if r.pending > 0 {
pend := fmt.Sprintf("%d test(s) pending", r.pending)
fmt.Printf(" %v\n\n", r.fancy.Cyan(pend))
}
if len(r.failures) > 0 {
fmt.Printf("%s \n\n", r.fancy.Red(fmt.Sprintf(" %d tests failed:", len(r.failures))))
}
for i, failure := range r.failures {
fmt.Printf(" %d) %s:\n\n", i+1, failure.testName)
fmt.Printf(" %s\n", r.fancy.Red(failure.message))
for _, stackItem := range failure.stack {
fmt.Printf(" %s\n", r.fancy.Gray(stackItem))
}
}
}

21
vendor/github.com/franela/goblin/resolver.go

@ -0,0 +1,21 @@
package goblin
import (
"runtime/debug"
"strings"
)
func ResolveStack(skip int) []string {
return cleanStack(debug.Stack(), skip)
}
func cleanStack(stack []byte, skip int) []string {
arrayStack := strings.Split(string(stack), "\n")
var finalStack []string
for i := skip; i < len(arrayStack); i++ {
if strings.Contains(arrayStack[i], ".go") {
finalStack = append(finalStack, arrayStack[i])
}
}
return finalStack
}

8
vendor/vendor.json

@ -144,6 +144,12 @@
"revision": "c0d7d3282e4c14991a4814de7eae4774e388de61",
"revisionTime": "2016-10-07T22:43:33Z"
},
{
"checksumSHA1": "ip3Xz/dILw2RMM6Z0MzAj5TUZ/c=",
"path": "github.com/franela/goblin",
"revision": "2fa789fd0c6b7975acbfb89a04830b4081a7b0e9",
"revisionTime": "2017-01-11T05:10:28Z"
},
{
"checksumSHA1": "cVyhKIRI2gQrgpn5qrBeAqErmWM=",
"path": "github.com/go-ini/ini",
@ -175,5 +181,5 @@
"revisionTime": "2016-10-06T02:47:49Z"
}
],
"rootPath": "github.com/drone-plugins/drone-terraform"
"rootPath": "github.com/jmccann/drone-terraform"
}

Loading…
Cancel
Save