Update drone (#44)
* Recovery drone file * Fix makefile * Update Makefile * Fix makefile * Fix makefile * Disable make lint on drone temprory * Update github.com/franela/goblin * update drone file * go vendor mode * go test can itterate itselve * Update Makefile Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
Родитель
0fbd0a0684
Коммит
ba36357970
265
.drone.yml
265
.drone.yml
|
@ -1,149 +1,166 @@
|
|||
---
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /srv/app
|
||||
base: /go
|
||||
path: src/github.com/go-gitea/lgtm
|
||||
|
||||
pipeline:
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
steps:
|
||||
- name: test
|
||||
pull: always
|
||||
image: golang:1.15
|
||||
commands:
|
||||
- make clean
|
||||
- make vet
|
||||
#- make lint
|
||||
- make test
|
||||
- make build
|
||||
settings:
|
||||
group: testing
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
CGO_ENABLED: "1"
|
||||
commands:
|
||||
- make clean
|
||||
- make vet
|
||||
- make lint
|
||||
- make test
|
||||
- make build
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
|
||||
GOSUMDB: sum.golang.org
|
||||
CGO_ENABLED: 1
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
- pull_request
|
||||
|
||||
test-mysql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
- name: test-mysql
|
||||
pull: always
|
||||
image: golang:1.15
|
||||
commands:
|
||||
- make test-mysql
|
||||
settings:
|
||||
group: testing
|
||||
commands:
|
||||
- make test-mysql
|
||||
when:
|
||||
event: [ push ]
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
test-pgsql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
- name: test-pgsql
|
||||
pull: always
|
||||
image: golang:1.15
|
||||
commands:
|
||||
- make test-pgsql
|
||||
settings:
|
||||
group: testing
|
||||
commands:
|
||||
- make test-pgsql
|
||||
when:
|
||||
event: [ push ]
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
coverage:
|
||||
image: plugins/codecov
|
||||
name: ${DRONE_REPO}
|
||||
secrets: [ codecov_token ]
|
||||
when:
|
||||
event: [ push, pull_request ]
|
||||
- name: coverage
|
||||
pull: default
|
||||
image: plugins/codecov
|
||||
environment:
|
||||
CODECOV_TOKEN:
|
||||
from_secret: codecov_token
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
updater:
|
||||
image: appleboy/golang-testing:1.9.2
|
||||
pull: true
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
event: [ tag ]
|
||||
- name: updater
|
||||
pull: always
|
||||
image: appleboy/golang-testing:1.9.2
|
||||
commands:
|
||||
- make release
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
|
||||
updater:
|
||||
image: appleboy/golang-testing:1.9.2
|
||||
pull: true
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker:17.05
|
||||
pull: true
|
||||
secrets: [ docker_username, docker_password ]
|
||||
- name: docker
|
||||
pull: always
|
||||
image: plugins/docker:17.05
|
||||
settings:
|
||||
group: release
|
||||
repo: gitea/lgtm
|
||||
auto_tag: true
|
||||
dockerfile: Dockerfile
|
||||
when:
|
||||
event: [ push, tag ]
|
||||
environment:
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: docker_password
|
||||
DOCKER_USERNAME:
|
||||
from_secret: docker_username
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
|
||||
docker:
|
||||
image: plugins/docker:17.05
|
||||
pull: true
|
||||
secrets: [ docker_username, docker_password ]
|
||||
group: release
|
||||
repo: gitea/lgtm
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
release:
|
||||
image: plugins/s3:1
|
||||
pull: true
|
||||
group: release
|
||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||
- name: release
|
||||
pull: always
|
||||
image: plugins/s3:1
|
||||
settings:
|
||||
bucket: releases
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /lgtm/master
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
release:
|
||||
image: plugins/s3:1
|
||||
pull: true
|
||||
group: release
|
||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||
bucket: releases
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /lgtm/${DRONE_TAG##v}
|
||||
when:
|
||||
event: [ tag ]
|
||||
target: "/lgtm/${DRONE_TAG##v}"
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: aws_access_key_id
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
from_secret: aws_secret_access_key
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
github:
|
||||
image: plugins/github-release:1
|
||||
pull: true
|
||||
group: release
|
||||
secrets: [ github_token ]
|
||||
- name: github
|
||||
pull: always
|
||||
image: plugins/github-release:1
|
||||
settings:
|
||||
files:
|
||||
- dist/release/*
|
||||
when:
|
||||
event: [ tag ]
|
||||
- "dist/release/*"
|
||||
group: release
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: github_token
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
discord:
|
||||
image: appleboy/drone-discord
|
||||
secrets: [ discord_webhook_id, discord_webhook_token ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
status: [ changed, failure ]
|
||||
- name: discord
|
||||
pull: default
|
||||
image: appleboy/drone-discord
|
||||
environment:
|
||||
DISCORD_WEBHOOK_ID:
|
||||
from_secret: discord_webhook_id
|
||||
DISCORD_WEBHOOK_TOKEN:
|
||||
from_secret: discord_webhook_token
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
status:
|
||||
- changed
|
||||
- failure
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
- MYSQL_DATABASE=test
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
when:
|
||||
event: [ push ]
|
||||
- name: mysql
|
||||
pull: default
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: test
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
pgsql:
|
||||
image: postgres:9.5
|
||||
environment:
|
||||
- POSTGRES_DB=test
|
||||
when:
|
||||
event: [ push ]
|
||||
- name: pgsql
|
||||
pull: default
|
||||
image: postgres:9.5
|
||||
environment:
|
||||
POSTGRES_DB: test
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
|
18
Makefile
18
Makefile
|
@ -11,7 +11,7 @@ LDFLAGS += -X "github.com/go-gitea/lgtm/version.VersionDev=$(SHA)"
|
|||
|
||||
TARGETS ?= linux darwin windows
|
||||
ARCHS ?= amd64 386
|
||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||
PACKAGES ?= $(shell go list -mod=vendor ./... | grep -v /vendor/)
|
||||
|
||||
ifneq ($(shell uname), Darwin)
|
||||
EXTLDFLAGS = -extldflags "-static" $(null)
|
||||
|
@ -58,15 +58,19 @@ vet:
|
|||
go vet $(PACKAGES)
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@which golint > /dev/null; if [ $$? -ne 0 ]; then \
|
||||
go get -u github.com/golang/lint/golint; \
|
||||
lint: golangci-lint
|
||||
|
||||
.PHONY: golangci-lint
|
||||
golangci-lint:
|
||||
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
export BINARY="golangci-lint"; \
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.31.0; \
|
||||
fi
|
||||
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
|
||||
golangci-lint run --timeout 5m
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
for PKG in $(PACKAGES); do go test -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
go test -mod=vendor -cover -coverprofile coverage.out $(PACKAGES) || exit 1
|
||||
|
||||
.PHONY: check
|
||||
check: test
|
||||
|
@ -87,7 +91,7 @@ install: $(SOURCES)
|
|||
build: $(BIN)/$(EXECUTABLE)
|
||||
|
||||
$(BIN)/$(EXECUTABLE): $(SOURCES)
|
||||
go build -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
go build -mod=vendor -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
release: release-dirs release-build release-copy release-check
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/Sirupsen/logrus v0.6.7-0.20150309155839-2cea0f0d141f
|
||||
github.com/dgrijalva/jwt-go v2.2.1-0.20150401180636-c48cfd5d9711+incompatible
|
||||
github.com/elazarl/go-bindata-assetfs v0.0.0-20150414184409-bea323321994
|
||||
github.com/franela/goblin v0.0.0-20150112000940-2042c4d610d2
|
||||
github.com/franela/goblin v0.0.0-20201006155558-6240afcb2eb7
|
||||
github.com/gin-gonic/contrib v0.0.0-20150815172543-14f66d54cdb9
|
||||
github.com/gin-gonic/gin v0.0.0-20160414233928-5caaac4c5c71
|
||||
github.com/go-sql-driver/mysql v1.2.1-0.20151112163355-d512f204a577
|
||||
|
|
2
go.sum
2
go.sum
|
@ -8,6 +8,8 @@ github.com/elazarl/go-bindata-assetfs v0.0.0-20150414184409-bea323321994 h1:6Ygv
|
|||
github.com/elazarl/go-bindata-assetfs v0.0.0-20150414184409-bea323321994/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/franela/goblin v0.0.0-20150112000940-2042c4d610d2 h1:PcbwRGOqYeTQw76GRthRaxNGII82C/kx46ll3aNqDMQ=
|
||||
github.com/franela/goblin v0.0.0-20150112000940-2042c4d610d2/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goblin v0.0.0-20201006155558-6240afcb2eb7 h1:eUae9KtuHjNg5e7DYkn57S/M/ndIICmV1bWs9ejYCx4=
|
||||
github.com/franela/goblin v0.0.0-20201006155558-6240afcb2eb7/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
|
||||
github.com/gin-gonic/contrib v0.0.0-20150815172543-14f66d54cdb9 h1:gISPkiYdlRqAEbns25dOAoT/w5dxhI4ACWUYfTr3dFQ=
|
||||
github.com/gin-gonic/contrib v0.0.0-20150815172543-14f66d54cdb9/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg=
|
||||
github.com/gin-gonic/gin v0.0.0-20160414233928-5caaac4c5c71 h1:ML+SQEYkMC4dDaXPRUyIOI0mbbXBdIvquVspxzzJ54E=
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.1.2
|
||||
- tip
|
||||
notifications:
|
||||
email:
|
||||
- ionathan@gmail.com
|
||||
- marcosnils@gmail.com
|
|
@ -1,23 +1,22 @@
|
|||
[![Build Status](https://travis-ci.org/franela/goblin.png?branch=master)](https://travis-ci.org/franela/goblin)
|
||||
Goblin
|
||||
======
|
||||
|
||||
[![Build Status](https://travis-ci.org/franela/goblin.svg)](https://travis-ci.org/franela/goblin)
|
||||
[![Go Reportcard](https://goreportcard.com/badge/github.com/franela/goblin)](https://goreportcard.com/report/github.com/franela/goblin)
|
||||
[![GoDoc](https://godoc.org/github.com/franela/goblin?status.svg)](https://godoc.org/github.com/franela/goblin)
|
||||
[![License](https://img.shields.io/github/license/franela/goblin.svg)](https://github.com/franela/goblin/blob/master/LICENSE.md)
|
||||
[![Release](https://img.shields.io/github/release/franela/goblin.svg)](https://github.com/franela/goblin/releases/latest)
|
||||
|
||||
|
||||
A [Mocha](http://mochajs.org/) like BDD testing framework written in Go that requires no additional dependencies. Requires no extensive documentation nor complicated steps to get it running.
|
||||
|
||||
![](https://github.com/marcosnils/goblin/blob/master/goblin_logo.jpg?raw=true)
|
||||
|
||||
A [Mocha](http://visionmedia.github.io/mocha/) 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
|
||||
rigorousness of Go way of testing, we wanted to bring a new tool to
|
||||
write self-describing and comprehensive code.
|
||||
|
||||
|
||||
|
@ -25,12 +24,15 @@ write self-describing and comprehensive code.
|
|||
What do I get with it?
|
||||
----------------------
|
||||
|
||||
- Run tests as usual with `go test`
|
||||
- Colorful reports and beautiful syntax
|
||||
- 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)
|
||||
- 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
|
||||
|
@ -54,13 +56,20 @@ import (
|
|||
func Test(t *testing.T) {
|
||||
g := Goblin(t)
|
||||
g.Describe("Numbers", func() {
|
||||
// Passing Test
|
||||
g.It("Should add two numbers ", func() {
|
||||
g.Assert(1+1).Equal(2)
|
||||
})
|
||||
// Failing Test
|
||||
g.It("Should match equal numbers", func() {
|
||||
g.Assert(2).Equal(4)
|
||||
})
|
||||
// Pending Test
|
||||
g.It("Should substract two numbers")
|
||||
// Excluded Test
|
||||
g.Xit("Should add two numbers ", func() {
|
||||
g.Assert(3+1).Equal(4)
|
||||
})
|
||||
})
|
||||
}
|
||||
```
|
||||
|
@ -102,12 +111,12 @@ package foobar
|
|||
|
||||
import (
|
||||
"testing"
|
||||
. "github.com/franela/goblin"
|
||||
goblin "github.com/franela/goblin"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
g := Goblin(t)
|
||||
g := goblin.Goblin(t)
|
||||
|
||||
//special hook for gomega
|
||||
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })
|
||||
|
@ -120,13 +129,21 @@ func Test(t *testing.T) {
|
|||
}
|
||||
```
|
||||
|
||||
TODO:
|
||||
|
||||
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
|
||||
|
||||
|
||||
Contributing
|
||||
-----
|
||||
|
||||
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:).
|
||||
We do have a couple of [issues](https://github.com/franela/goblin/issues) pending. Feel free to contribute and send us PRs (with tests please :smile:).
|
||||
|
||||
Contributions:
|
||||
Special Thanks
|
||||
------------
|
||||
|
||||
Special thanks to [Leandro Reox](https://github.com/leandroreox) (Leitan) for the goblin logo.
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Assertion represents a fact stated about a source object. It contains the
|
||||
// source object and function to call
|
||||
type Assertion struct {
|
||||
src interface{}
|
||||
fail func(interface{})
|
||||
|
@ -27,33 +29,108 @@ func objectsAreEqual(a, b interface{}) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func formatMessages(messages ...string) string {
|
||||
if len(messages) > 0 {
|
||||
return ", " + strings.Join(messages, " ")
|
||||
// Format series of messages provided to an assertion. Separate messages from
|
||||
// the preamble of assertion with a comma and concatenate messages using spaces.
|
||||
// Messages that are purely whitespace will be wrapped with square brackets, so
|
||||
// the developer can glean that something was actually reported in a message.
|
||||
func formatMessages(messages ...interface{}) string {
|
||||
// Concatenate messages together.
|
||||
var fm strings.Builder
|
||||
for _, message := range messages {
|
||||
fm.WriteString(" ")
|
||||
|
||||
// Format message then wrap with square brackets if only
|
||||
// whitespace.
|
||||
m := fmt.Sprintf("%v", message)
|
||||
if strings.TrimSpace(m) == "" {
|
||||
m = fmt.Sprintf("[%s]", m)
|
||||
}
|
||||
fm.WriteString(m)
|
||||
}
|
||||
return ""
|
||||
|
||||
if fm.Len() == 0 {
|
||||
return ""
|
||||
}
|
||||
return "," + fm.String()
|
||||
}
|
||||
|
||||
func (a *Assertion) Eql(dst interface{}) {
|
||||
a.Equal(dst)
|
||||
// Eql is a shorthand alias of Equal for convenience
|
||||
func (a *Assertion) Eql(dst interface{}, messages ...interface{}) {
|
||||
a.Equal(dst, messages)
|
||||
}
|
||||
|
||||
func (a *Assertion) Equal(dst interface{}) {
|
||||
// Equal takes a destination object and asserts that a source object and
|
||||
// destination object are equal to one another. It will fail the assertion and
|
||||
// print a corresponding message if the objects are not equivalent.
|
||||
func (a *Assertion) Equal(dst interface{}, messages ...interface{}) {
|
||||
if !objectsAreEqual(a.src, dst) {
|
||||
a.fail(fmt.Sprintf("%v %s %v", a.src, "does not equal", dst))
|
||||
a.fail(fmt.Sprintf("%#v %s %#v%s", a.src, "does not equal", dst,
|
||||
formatMessages(messages...)))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Assertion) IsTrue(messages ...string) {
|
||||
// IsTrue asserts that a source is equal to true. Optional messages can be
|
||||
// provided for inclusion in the displayed message if the assertion fails. It
|
||||
// will fail the assertion if the source does not resolve to true.
|
||||
func (a *Assertion) IsTrue(messages ...interface{}) {
|
||||
if !objectsAreEqual(a.src, true) {
|
||||
message := fmt.Sprintf("%v %s%s", a.src, "expected false to be truthy", formatMessages(messages...))
|
||||
a.fail(fmt.Sprintf("%v %s%s", a.src,
|
||||
"expected false to be truthy",
|
||||
formatMessages(messages...)))
|
||||
}
|
||||
}
|
||||
|
||||
// IsFalse asserts that a source is equal to false. Optional messages can be
|
||||
// provided for inclusion in the displayed message if the assertion fails. It
|
||||
// will fail the assertion if the source does not resolve to false.
|
||||
func (a *Assertion) IsFalse(messages ...interface{}) {
|
||||
if !objectsAreEqual(a.src, false) {
|
||||
a.fail(fmt.Sprintf("%v %s%s", a.src,
|
||||
"expected true to be falsey",
|
||||
formatMessages(messages...)))
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil asserts that source is nil.
|
||||
func (a *Assertion) IsNil(messages ...interface{}) {
|
||||
if !objectsAreEqual(a.src, nil) {
|
||||
message := fmt.Sprintf("%v %s%v", a.src, "expected to be nil", 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...))
|
||||
// IsNotNil asserts that source is not nil.
|
||||
func (a *Assertion) IsNotNil(messages ...interface{}) {
|
||||
if objectsAreEqual(a.src, nil) {
|
||||
message := fmt.Sprintf("%v %s%v", a.src, "is nil", formatMessages(messages...))
|
||||
|
||||
a.fail(message)
|
||||
}
|
||||
}
|
||||
|
||||
// IsZero asserts that source is a zero value for its respective type.
|
||||
// If it is a structure, for example, all of its fields must have their
|
||||
// respective zero value: "" for strings, 0 for int, etc. Slices, arrays
|
||||
// and maps are only considered zero if they are nil. To check if these
|
||||
// type of values are empty or not, use the len() from the data source
|
||||
// with IsZero(). Example: g.Assert(len(list)).IsZero().
|
||||
func (a *Assertion) IsZero(messages ...interface{}) {
|
||||
valueOf := reflect.ValueOf(a.src)
|
||||
|
||||
if !valueOf.IsZero() {
|
||||
message := fmt.Sprintf("%#v %s%v", a.src, "is not a zero value", formatMessages(messages...))
|
||||
|
||||
a.fail(message)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotZero asserts the contrary of IsZero.
|
||||
func (a *Assertion) IsNotZero(messages ...interface{}) {
|
||||
valueOf := reflect.ValueOf(a.src)
|
||||
|
||||
if valueOf.IsZero() {
|
||||
message := fmt.Sprintf("%#v %s%v", a.src, "is a zero value", formatMessages(messages...))
|
||||
a.fail(message)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module github.com/franela/goblin
|
||||
|
||||
go 1.14
|
|
@ -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}
|
|
@ -3,7 +3,9 @@ package goblin
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
@ -14,6 +16,11 @@ type Runnable interface {
|
|||
run(*G) bool
|
||||
}
|
||||
|
||||
type Itable interface {
|
||||
run(*G) bool
|
||||
failed(string, []string)
|
||||
}
|
||||
|
||||
func (g *G) Describe(name string, h func()) {
|
||||
d := &Describe{name: name, h: h, parent: g.parent}
|
||||
|
||||
|
@ -27,25 +34,31 @@ func (g *G) Describe(name string, h func()) {
|
|||
|
||||
g.parent = d.parent
|
||||
|
||||
if g.parent == nil {
|
||||
g.reporter.begin()
|
||||
if g.parent == nil && d.hasTests {
|
||||
g.reporter.Begin()
|
||||
if d.run(g) {
|
||||
g.t.Fail()
|
||||
}
|
||||
g.reporter.end()
|
||||
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
|
||||
name string
|
||||
h func()
|
||||
children []Runnable
|
||||
befores []func()
|
||||
afters []func()
|
||||
afterEach []func()
|
||||
beforeEach []func()
|
||||
justBeforeEach []func()
|
||||
hasTests bool
|
||||
parent *Describe
|
||||
}
|
||||
|
||||
func (d *Describe) runBeforeEach() {
|
||||
|
@ -58,52 +71,101 @@ func (d *Describe) runBeforeEach() {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *Describe) runAfterEach() {
|
||||
|
||||
func (d *Describe) runJustBeforeEach() {
|
||||
if d.parent != nil {
|
||||
d.parent.runAfterEach()
|
||||
d.parent.runJustBeforeEach()
|
||||
}
|
||||
|
||||
for _, b := range d.justBeforeEach {
|
||||
b()
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Describe) runAfterEach() {
|
||||
|
||||
for _, a := range d.afterEach {
|
||||
a()
|
||||
}
|
||||
|
||||
if d.parent != nil {
|
||||
d.parent.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 {
|
||||
stack []string
|
||||
testName string
|
||||
message string
|
||||
Stack []string
|
||||
TestName string
|
||||
Message string
|
||||
}
|
||||
|
||||
type It struct {
|
||||
h interface{}
|
||||
name string
|
||||
parent *Describe
|
||||
failure *Failure
|
||||
failureMu sync.RWMutex
|
||||
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
|
||||
}
|
||||
|
||||
runIt(g, it)
|
||||
|
||||
failed := false
|
||||
it.failureMu.RLock()
|
||||
if it.failure != nil {
|
||||
failed = true
|
||||
}
|
||||
it.failureMu.RUnlock()
|
||||
|
||||
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.failureMu.Lock()
|
||||
defer it.failureMu.Unlock()
|
||||
it.failure = &Failure{Stack: stack, Message: msg, TestName: it.parent.name + " " + it.name}
|
||||
}
|
||||
|
||||
type Xit struct {
|
||||
h interface{}
|
||||
name string
|
||||
parent *Describe
|
||||
|
@ -112,57 +174,35 @@ type It struct {
|
|||
isAsync bool
|
||||
}
|
||||
|
||||
func (it *It) run(g *G) bool {
|
||||
g.currentIt = it
|
||||
func (xit *Xit) run(g *G) bool {
|
||||
g.currentIt = xit
|
||||
|
||||
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
|
||||
g.reporter.ItIsExcluded(xit.name)
|
||||
return false
|
||||
}
|
||||
|
||||
func (it *It) failed(msg string, stack []string) {
|
||||
it.failure = &Failure{stack: stack, message: msg, testName: it.parent.name + " " + it.name}
|
||||
func (xit *Xit) failed(msg string, stack []string) {
|
||||
xit.failure = nil
|
||||
}
|
||||
|
||||
var timeout *time.Duration
|
||||
var isTty *bool
|
||||
|
||||
func init() {
|
||||
func parseFlags() {
|
||||
//Flag parsing
|
||||
timeout = flag.Duration("goblin.timeout", 5*time.Second, "Sets default timeouts for all tests")
|
||||
isTty = flag.Bool("goblin.tty", true, "Sets the default output format (color / monochrome)")
|
||||
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 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}
|
||||
parseFlags()
|
||||
g := &G{t: t, timeout: *timeout}
|
||||
var fancy TextFancier
|
||||
if *isTty {
|
||||
fancy = &TerminalFancier{}
|
||||
|
@ -174,50 +214,66 @@ func Goblin(t *testing.T, arguments ...string) *G {
|
|||
return g
|
||||
}
|
||||
|
||||
func runIt(g *G, h interface{}) {
|
||||
defer timeTrack(time.Now(), g)
|
||||
func runIt(g *G, it *It) {
|
||||
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 {
|
||||
if call, ok := it.h.(func()); ok {
|
||||
// the test is synchronous
|
||||
go func() { call(); g.shouldContinue <- true }()
|
||||
} else if call, ok := h.(func(Done)); ok {
|
||||
go func(c chan bool) {
|
||||
it.parent.runBeforeEach()
|
||||
it.parent.runJustBeforeEach()
|
||||
timeTrack(g, func() { call() })
|
||||
it.parent.runAfterEach()
|
||||
c <- true
|
||||
}(g.shouldContinue)
|
||||
} else if call, ok := it.h.(func(Done)); ok {
|
||||
doneCalled := 0
|
||||
go func() {
|
||||
call(func(msg ...interface{}) {
|
||||
if len(msg) > 0 {
|
||||
g.Fail(msg)
|
||||
} else {
|
||||
doneCalled++
|
||||
if doneCalled > 1 {
|
||||
g.Fail("Done called multiple times")
|
||||
go func(c chan bool) {
|
||||
it.parent.runBeforeEach()
|
||||
it.parent.runJustBeforeEach()
|
||||
timeTrack(g, func() {
|
||||
call(func(msg ...interface{}) {
|
||||
if len(msg) > 0 {
|
||||
g.Fail(msg)
|
||||
} else {
|
||||
doneCalled++
|
||||
if doneCalled > 1 {
|
||||
g.Fail("Done called multiple times")
|
||||
}
|
||||
it.parent.runAfterEach()
|
||||
c <- true
|
||||
}
|
||||
g.shouldContinue <- true
|
||||
}
|
||||
})
|
||||
})
|
||||
}()
|
||||
}(g.shouldContinue)
|
||||
} else {
|
||||
panic("Not implemented.")
|
||||
}
|
||||
select {
|
||||
case <-g.shouldContinue:
|
||||
case <-time.After(g.timeout):
|
||||
fmt.Println("Timedout")
|
||||
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
|
||||
currentIt Itable
|
||||
timeout time.Duration
|
||||
reporter Reporter
|
||||
timedOut bool
|
||||
shouldContinue chan bool
|
||||
mutex sync.Mutex
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
func (g *G) SetReporter(r Reporter) {
|
||||
|
@ -225,12 +281,35 @@ 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}
|
||||
if g.parent == nil {
|
||||
panic(fmt.Sprintf("It(\"%s\") block should be written inside Describe() block.", name))
|
||||
}
|
||||
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 (g *G) Xit(name string, h ...interface{}) {
|
||||
if matchesRegex(name) {
|
||||
xit := &Xit{name: name, parent: g.parent, reporter: g.reporter}
|
||||
notifyParents(g.parent)
|
||||
if len(h) > 0 {
|
||||
xit.h = h[0]
|
||||
}
|
||||
g.parent.children = append(g.parent.children, Runnable(xit))
|
||||
}
|
||||
}
|
||||
|
||||
func matchesRegex(value string) bool {
|
||||
if runRegex != nil {
|
||||
return runRegex.MatchString(value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func notifyParents(d *Describe) {
|
||||
|
@ -248,6 +327,10 @@ func (g *G) BeforeEach(h func()) {
|
|||
g.parent.beforeEach = append(g.parent.beforeEach, h)
|
||||
}
|
||||
|
||||
func (g *G) JustBeforeEach(h func()) {
|
||||
g.parent.justBeforeEach = append(g.parent.justBeforeEach, h)
|
||||
}
|
||||
|
||||
func (g *G) After(h func()) {
|
||||
g.parent.afters = append(g.parent.afters, h)
|
||||
}
|
||||
|
@ -260,21 +343,57 @@ 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 timeTrack(g *G, call func()) {
|
||||
t := time.Now()
|
||||
defer func() {
|
||||
g.reporter.ItTook(time.Since(t))
|
||||
}()
|
||||
call()
|
||||
}
|
||||
|
||||
func (g *G) Fail(error interface{}) {
|
||||
//Skips 7 stacks due to the functions between the stack and the test
|
||||
stack := ResolveStack(4)
|
||||
message := fmt.Sprintf("%v", error)
|
||||
g.currentIt.failed(message, stack)
|
||||
func (g *G) errorCommon(msg string, fatal bool) {
|
||||
if g.currentIt == nil {
|
||||
panic("Asserts should be written inside an It() block.")
|
||||
}
|
||||
g.currentIt.failed(msg, ResolveStack(9))
|
||||
if g.shouldContinue != nil {
|
||||
g.shouldContinue <- true
|
||||
}
|
||||
|
||||
if !g.timedOut {
|
||||
//Stop test function execution
|
||||
runtime.Goexit()
|
||||
if fatal {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
if !g.timedOut {
|
||||
//Stop test function execution
|
||||
runtime.Goexit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *G) Fail(error interface{}) {
|
||||
message := fmt.Sprintf("%v", error)
|
||||
g.errorCommon(message, true)
|
||||
}
|
||||
|
||||
func (g *G) FailNow() {
|
||||
g.t.FailNow()
|
||||
}
|
||||
|
||||
func (g *G) Failf(format string, args ...interface{}) {
|
||||
message := fmt.Sprintf(format, args...)
|
||||
g.errorCommon(message, true)
|
||||
}
|
||||
|
||||
func (g *G) Fatalf(format string, args ...interface{}) {
|
||||
message := fmt.Sprintf(format, args...)
|
||||
g.errorCommon(message, true)
|
||||
}
|
||||
|
||||
func (g *G) Errorf(format string, args ...interface{}) {
|
||||
message := fmt.Sprintf(format, args...)
|
||||
g.errorCommon(message, false)
|
||||
}
|
||||
|
||||
func (g *G) Helper() {
|
||||
g.t.Helper()
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 18 KiB После Ширина: | Высота: | Размер: 48 KiB |
|
@ -24,3 +24,7 @@ func (self *Monochrome) WithCheck(text string) string {
|
|||
func (self *Monochrome) Green(text string) string {
|
||||
return text
|
||||
}
|
||||
|
||||
func (self *Monochrome) Yellow(text string) string {
|
||||
return text
|
||||
}
|
||||
|
|
|
@ -4,19 +4,21 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Reporter interface {
|
||||
beginDescribe(string)
|
||||
endDescribe()
|
||||
begin()
|
||||
end()
|
||||
failure(*Failure)
|
||||
itTook(time.Duration)
|
||||
itFailed(string)
|
||||
itPassed(string)
|
||||
itIsPending(string)
|
||||
BeginDescribe(string)
|
||||
EndDescribe()
|
||||
Begin()
|
||||
End()
|
||||
Failure(*Failure)
|
||||
ItTook(time.Duration)
|
||||
ItFailed(string)
|
||||
ItPassed(string)
|
||||
ItIsPending(string)
|
||||
ItIsExcluded(string)
|
||||
}
|
||||
|
||||
type TextFancier interface {
|
||||
|
@ -24,14 +26,16 @@ type TextFancier interface {
|
|||
Gray(text string) string
|
||||
Cyan(text string) string
|
||||
Green(text string) string
|
||||
Yellow(text string) string
|
||||
WithCheck(text string) string
|
||||
}
|
||||
|
||||
type DetailedReporter struct {
|
||||
level, failed, passed, pending int
|
||||
failures []*Failure
|
||||
executionTime, totalExecutionTime time.Duration
|
||||
fancy TextFancier
|
||||
level, failed, passed, pending, excluded int
|
||||
failures []*Failure
|
||||
executionTime, totalExecutionTime time.Duration
|
||||
executionTimeMu sync.RWMutex
|
||||
fancy TextFancier
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) SetTextFancier(f TextFancier) {
|
||||
|
@ -57,6 +61,10 @@ func (self *TerminalFancier) Green(text string) string {
|
|||
return "\033[32m" + text + "\033[0m"
|
||||
}
|
||||
|
||||
func (self *TerminalFancier) Yellow(text string) string {
|
||||
return "\033[33m" + text + "\033[0m"
|
||||
}
|
||||
|
||||
func (self *TerminalFancier) WithCheck(text string) string {
|
||||
return "\033[32m\u2713\033[0m " + text
|
||||
}
|
||||
|
@ -65,7 +73,7 @@ func (r *DetailedReporter) getSpace() string {
|
|||
return strings.Repeat(" ", (r.level+1)*2)
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) failure(failure *Failure) {
|
||||
func (r *DetailedReporter) Failure(failure *Failure) {
|
||||
r.failures = append(r.failures, failure)
|
||||
}
|
||||
|
||||
|
@ -77,42 +85,52 @@ func (r *DetailedReporter) printWithCheck(text string) {
|
|||
fmt.Printf("%v%v\n", r.getSpace(), r.fancy.WithCheck(text))
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) beginDescribe(name string) {
|
||||
func (r *DetailedReporter) BeginDescribe(name string) {
|
||||
fmt.Println("")
|
||||
r.print(name)
|
||||
r.level++
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) endDescribe() {
|
||||
func (r *DetailedReporter) EndDescribe() {
|
||||
r.level--
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) itTook(duration time.Duration) {
|
||||
func (r *DetailedReporter) ItTook(duration time.Duration) {
|
||||
r.executionTimeMu.Lock()
|
||||
defer r.executionTimeMu.Unlock()
|
||||
r.executionTime = duration
|
||||
r.totalExecutionTime += duration
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) itFailed(name string) {
|
||||
func (r *DetailedReporter) ItFailed(name string) {
|
||||
r.failed++
|
||||
r.print(r.fancy.Red(strconv.Itoa(r.failed) + ") " + name))
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) itPassed(name string) {
|
||||
func (r *DetailedReporter) ItPassed(name string) {
|
||||
r.passed++
|
||||
r.printWithCheck(r.fancy.Gray(name))
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) itIsPending(name string) {
|
||||
func (r *DetailedReporter) ItIsPending(name string) {
|
||||
r.pending++
|
||||
r.print(r.fancy.Cyan("- " + name))
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) begin() {
|
||||
func (r *DetailedReporter) ItIsExcluded(name string) {
|
||||
r.excluded++
|
||||
r.print(r.fancy.Yellow("- " + name))
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) end() {
|
||||
func (r *DetailedReporter) Begin() {
|
||||
}
|
||||
|
||||
func (r *DetailedReporter) End() {
|
||||
comp := fmt.Sprintf("%d tests complete", r.passed)
|
||||
|
||||
r.executionTimeMu.RLock()
|
||||
t := fmt.Sprintf("(%d ms)", r.totalExecutionTime/time.Millisecond)
|
||||
r.executionTimeMu.RUnlock()
|
||||
|
||||
//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))
|
||||
|
@ -122,15 +140,20 @@ func (r *DetailedReporter) end() {
|
|||
fmt.Printf(" %v\n\n", r.fancy.Cyan(pend))
|
||||
}
|
||||
|
||||
if r.excluded > 0 {
|
||||
excl := fmt.Sprintf("%d test(s) excluded", r.excluded)
|
||||
fmt.Printf(" %v\n\n", r.fancy.Yellow(excl))
|
||||
}
|
||||
|
||||
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(" %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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ github.com/dgrijalva/jwt-go
|
|||
# github.com/elazarl/go-bindata-assetfs v0.0.0-20150414184409-bea323321994
|
||||
## explicit
|
||||
github.com/elazarl/go-bindata-assetfs
|
||||
# github.com/franela/goblin v0.0.0-20150112000940-2042c4d610d2
|
||||
# github.com/franela/goblin v0.0.0-20201006155558-6240afcb2eb7
|
||||
## explicit
|
||||
github.com/franela/goblin
|
||||
# github.com/gin-gonic/contrib v0.0.0-20150815172543-14f66d54cdb9
|
||||
|
|
Загрузка…
Ссылка в новой задаче