updated goblin test lib

This commit is contained in:
Brad Rydzewski 2016-03-07 11:51:06 -08:00
parent b0500836f1
commit 9559192fb5
7 changed files with 80 additions and 88 deletions

View file

@ -120,6 +120,15 @@ func Test(t *testing.T) {
}
```
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:
-----

View file

@ -3,6 +3,7 @@ package goblin
import (
"fmt"
"reflect"
"strings"
)
type Assertion struct {
@ -19,10 +20,6 @@ func objectsAreEqual(a, b interface{}) bool {
return true
}
if reflect.ValueOf(a) == reflect.ValueOf(b) {
return true
}
if fmt.Sprintf("%#v", a) == fmt.Sprintf("%#v", b) {
return true
}
@ -30,24 +27,33 @@ func objectsAreEqual(a, b interface{}) bool {
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", a.src) + " does not equal " + fmt.Sprintf("%v", dst))
a.fail(fmt.Sprintf("%#v %s %#v", a.src, "does not equal", dst))
}
}
func (a *Assertion) IsTrue() {
func (a *Assertion) IsTrue(messages ...string) {
if !objectsAreEqual(a.src, true) {
a.fail(fmt.Sprintf("%v", a.src) + " expected false to be truthy")
message := fmt.Sprintf("%v %s%s", a.src, "expected false to be truthy", formatMessages(messages...))
a.fail(message)
}
}
func (a *Assertion) IsFalse() {
func (a *Assertion) IsFalse(messages ...string) {
if !objectsAreEqual(a.src, false) {
a.fail(fmt.Sprintf("%v", a.src) + " expected true to be falsey")
message := fmt.Sprintf("%v %s%s", a.src, "expected true to be falsey", formatMessages(messages...))
a.fail(message)
}
}

View file

@ -3,8 +3,9 @@ package goblin
import (
"flag"
"fmt"
"os"
"regexp"
"runtime"
"sync"
"testing"
"time"
)
@ -28,7 +29,7 @@ func (g *G) Describe(name string, h func()) {
g.parent = d.parent
if g.parent == nil {
if g.parent == nil && d.hasTests {
g.reporter.begin()
if d.run(g) {
g.t.Fail()
@ -71,31 +72,28 @@ func (d *Describe) runAfterEach() {
}
func (d *Describe) run(g *G) bool {
g.reporter.beginDescribe(d.name)
failed := ""
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 _, r := range d.children {
if r.run(g) {
failed = true
}
}
}
if d.hasTests {
for _, a := range d.afters {
a()
}
g.reporter.endDescribe()
}
g.reporter.endDescribe()
return failed != ""
return failed
}
type Failure struct {
@ -145,26 +143,29 @@ func (it *It) failed(msg string, stack []string) {
it.failure = &Failure{stack: stack, message: msg, testName: it.parent.name + " " + it.name}
}
var timeout *time.Duration
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() {
//Flag parsing
timeout = flag.Duration("goblin.timeout", 5*time.Second, "Sets default timeouts for all tests")
flag.Parse()
parseFlags()
}
func Goblin(t *testing.T, arguments ...string) *G {
var gobtimeout = timeout
if arguments != nil {
//Programatic flags
var args = flag.NewFlagSet("Goblin arguments", flag.ContinueOnError)
gobtimeout = args.Duration("goblin.timeout", 5*time.Second, "Sets timeouts for tests")
args.Parse(arguments)
}
g := &G{t: t, timeout: *gobtimeout}
fd := os.Stdout.Fd()
g := &G{t: t, timeout: *timeout}
var fancy TextFancier
if IsTerminal(int(fd)) {
if *isTty {
fancy = &TerminalFancier{}
} else {
fancy = &Monochrome{}
@ -176,14 +177,16 @@ func Goblin(t *testing.T, arguments ...string) *G {
func runIt(g *G, h interface{}) {
defer timeTrack(time.Now(), g)
g.mutex.Lock()
g.timedOut = false
g.mutex.Unlock()
g.shouldContinue = make(chan bool)
if call, ok := h.(func()); ok {
// the test is synchronous
go func() { call(); g.shouldContinue <- true }()
go func(c chan bool) { call(); c <- true }(g.shouldContinue)
} else if call, ok := h.(func(Done)); ok {
doneCalled := 0
go func() {
go func(c chan bool) {
call(func(msg ...interface{}) {
if len(msg) > 0 {
g.Fail(msg)
@ -192,17 +195,16 @@ func runIt(g *G, h interface{}) {
if doneCalled > 1 {
g.Fail("Done called multiple times")
}
g.shouldContinue <- true
c <- true
}
})
}()
}(g.shouldContinue)
} else {
panic("Not implemented.")
}
select {
case <-g.shouldContinue:
case <-time.After(g.timeout):
fmt.Println("Timedout")
//Set to nil as it shouldn't continue
g.shouldContinue = nil
g.timedOut = true
@ -218,6 +220,7 @@ type G struct {
reporter Reporter
timedOut bool
shouldContinue chan bool
mutex sync.Mutex
}
func (g *G) SetReporter(r Reporter) {
@ -225,12 +228,21 @@ func (g *G) SetReporter(r Reporter) {
}
func (g *G) It(name string, h ...interface{}) {
it := &It{name: name, parent: g.parent, reporter: g.reporter}
notifyParents(g.parent)
if len(h) > 0 {
it.h = h[0]
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))
}
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) {
@ -272,9 +284,11 @@ func (g *G) Fail(error interface{}) {
if g.shouldContinue != nil {
g.shouldContinue <- true
}
g.mutex.Lock()
defer g.mutex.Unlock()
if !g.timedOut {
//Stop test function execution
runtime.Goexit()
}
}

View file

@ -1,13 +0,0 @@
package goblin
import (
"syscall"
"unsafe"
)
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
var termios syscall.Termios
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0
}

View file

@ -1,12 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
package goblin
import "syscall"
const ioctlReadTermios = syscall.TIOCGETA
const ioctlWriteTermios = syscall.TIOCSETA

View file

@ -1,12 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
package goblin
import "syscall"
const ioctlReadTermios = syscall.TCGETS
const ioctlWriteTermios = syscall.TCSETS

4
vendor/vendor.json vendored
View file

@ -50,8 +50,8 @@
},
{
"path": "github.com/franela/goblin",
"revision": "a99b1e87ecb6884721c6586e8846ec368234fb9a",
"revisionTime": "2014-07-25T18:08:57-07:00"
"revision": "889391d730237f8aca06ce3e62975112983f96b4",
"revisionTime": "2016-01-23T18:11:54-03:00"
},
{
"path": "github.com/gin-gonic/gin",