onsi / gomega Goto Github PK
View Code? Open in Web Editor NEWGinkgo's Preferred Matcher Library
Home Page: http://onsi.github.io/gomega/
License: MIT License
Ginkgo's Preferred Matcher Library
Home Page: http://onsi.github.io/gomega/
License: MIT License
This a better approach to integrate with other testing frameworks, since it doesn't require any special function to be implemented by the testing framework.
This is very very useful for integration tests.
Lovely documentation; however there are a number of (trivial) errors in it. How can I suggest some changes? Can I make pull requests against the docs?
A couple of new things have landed that aren't in the docs yet:
RouteToHandler
UseStringerRepresentation
and MaxDepth
On a whim I ran the gomega test suite and got the error below. Running it again succeeds. Running again with --seed=1404357757 passes fine.
$ ginkgo --noColor -r
[1404357757] Gomega - 38/38 specs •••••••••••••••••••
GOMEGA DEPRECATION WARNING
You are using a custom matcher of type:
*gomega.deprecatedBeTrueMatcher
that conforms to a deprecated matcher interface.
Please update your matcher, the old style will be removed in Gomega 1.0.
••••••••••••••••••• SUCCESS! 2.782168749s PASS
[1404357757] Format Suite - 29/29 specs ••••••••••••••••••••••••••••• SUCCESS! 2.698964ms PASS
[1404357757] Gbytes Suite - 23/23 specs ••••••••••••••••••••••• SUCCESS! 112.892583ms PASS
[1404357757] Gexec Suite - 20/20 specs •••••••••••••••••••• SUCCESS! 1.31294607s PASS
[1404357757] GHTTP Suite - 33/33 specs ••••••••••••••••••••••••••••••••• SUCCESS! 19.657667ms PASS
[1404357757] Gomega - 102/102 specs •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
------------------------------
• Failure [0.005 seconds]
HaveKey when the passed in key is actually a matcher [It] should fail if the matcher ever fails
/home/src/golang/src/github.com/onsi/gomega/matchers/have_key_matcher_test.go:59
Expected
<bool>: true
to be false
/home/src/golang/src/github.com/onsi/gomega/matchers/have_key_matcher_test.go:57
------------------------------
••••••••••••••
Summarizing 1 Failure:
[Fail] HaveKey when the passed in key is actually a matcher [It] should fail if the matcher ever fails
/home/src/golang/src/github.com/onsi/gomega/matchers/have_key_matcher_test.go:57
Ran 102 of 102 Specs in 0.079 seconds
FAIL! -- 101 Passed | 1 Failed | 0 Pending | 0 Skipped --- FAIL: Test (0.08 seconds)
FAIL
Ginkgo ran 6 suites in 5.931499584s
Test Suite Failed
After making the changes you requested in BeTemporally I hit the same error in HaveKeyWithValue (the above is in HaveKey):
$ ginkgo --noColor -r --seed=1404357757
[1404357757] Gomega - 38/38 specs •••••••••••••••••••
GOMEGA DEPRECATION WARNING
You are using a custom matcher of type:
*gomega.deprecatedBeTrueMatcher
that conforms to a deprecated matcher interface.
Please update your matcher, the old style will be removed in Gomega 1.0.
••••••••••••••••••• SUCCESS! 2.78199795s PASS
[1404357757] Format Suite - 29/29 specs ••••••••••••••••••••••••••••• SUCCESS! 3.212362ms PASS
[1404357757] Gbytes Suite - 23/23 specs ••••••••••••••••••••••• SUCCESS! 113.542916ms PASS
[1404357757] Gexec Suite - 20/20 specs •••••••••••••••••••• SUCCESS! 1.313654093s PASS
[1404357757] GHTTP Suite - 33/33 specs ••••••••••••••••••••••••••••••••• SUCCESS! 19.336928ms PASS
[1404357757] Gomega - 102/102 specs •••
------------------------------
• Failure [0.004 seconds]
HaveKeyWithValue when the passed in key is actually a matcher [It] should fail if the matcher ever fails
/home/src/golang/src/github.com/rightscale/gomega/matchers/have_key_value_matcher_test.go:63
Expected an error to have occured. Got:
<nil>: nil
/home/src/golang/src/github.com/rightscale/gomega/matchers/have_key_value_matcher_test.go:62
------------------------------
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Summarizing 1 Failure:
[Fail] HaveKeyWithValue when the passed in key is actually a matcher [It] should fail if the matcher ever fails
/home/src/golang/src/github.com/rightscale/gomega/matchers/have_key_value_matcher_test.go:62
Ran 102 of 102 Specs in 0.080 seconds
FAIL! -- 101 Passed | 1 Failed | 0 Pending | 0 Skipped --- FAIL: Test (0.08 seconds)
FAIL
Ginkgo ran 6 suites in 5.818125647s
Test Suite Failed
Running it again succeeds. Looking at the test I don't get what could be non-deterministic.
The changes to he OmegaMatcher interface were disruptive. Add back support for the old matcher style, but include a deprecation warning,
For example, a channel will never Receive() once it is closed. And Eventually(c).Should(Receive()) should fail early.
This does not make sense for all matchers, however. So it should be opt-in on a case by case basis. This also means we don't have to break backward compatibility on the matcher interface.
Gomega just hit 1.0-beta
In a week or so I'll bump it to 1.0 - so now is the time to chime in if you have any backwards-incompatible concerns about the DSL!
We'd like a new function ValueOf
that works like this:
var wasCalled bool
func ValueOf(p interface{}) func() interface{} {
return func() interface{} {
return reflect.Indirect(reflect.ValueOf(p)).Interface()
}
}
It("sets the value of the local variable", func() {
// Do something that sets the value of `wasCalled`
Eventually(ValueOf(&wasCalled)).Should(BeTrue())
})
171 var outBuffer bytes.Buffer
172 oldWriter := ginkgo.GinkgoWriter
173 ginkgo.GinkgoWriter = bufio.NewWriter(&outBuffer)
174 cfOutBuffer := EnvCf(env, args...).Wait(10 * time.Minute).Out
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x70d77d]
goroutine 394 [running]:
github.com/onsi/gomega/internal/asyncassertion.func·001(0x87d670, 0x9)
/root/go/src/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go:133 +0x4cd
github.com/onsi/gomega/internal/asyncassertion.(_AsyncAssertion).match(0xc20851f900, 0x7f69eb7e64d8, 0xc20832d120, 0xc20832d101, 0x0, 0x0, 0x0, 0xffffffffffffffff)
/root/go/src/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go:155 +0x440
github.com/onsi/gomega/internal/asyncassertion.(_AsyncAssertion).Should(0xc20851f900, 0x7f69eb7e64d8, 0xc20832d120, 0x0, 0x0, 0x0, 0xc20851f900)
/root/go/src/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go:47 +0x5f
github.com/onsi/gomega/gexec.(*Session).Wait(0xc208403a10, 0xc20815d838, 0x1, 0x1, 0x8)
/root/go/src/github.com/onsi/gomega/gexec/session.go:140 +0xfa
ghttp.Server doesn't allow you to have multiple concurrent requests. Does the lock really need to be on the lifetime of the request?
Couldn't the lock be released once the book keeping has been completed?
Came across this usecase today and it seems to make more sense anyway. One cannot receive from a closed channel -- attempting to do so is not an error.
c.f. http://onsi.github.io/gomega/#handling-errors --
"and the match only succeeds if all subsequent arguments are required to be nil or zero-valued."
This confuses me. I think that the following was the intended meaning:
"and the match only suceeds if all subsequent arguments are nil or zero-valued"
Its nice to have the feature that allows us to report how high up the stack the problem originated. Besides the fact that it may not work all that well given nested invocations, the stack currently presented doesn't show where the root cause was. Would it be more useful to use the value to hint at how much of the stack should be displayed vs just displaying the "caller"? That way you have context as to where it might have originated as well as what triggered the failure.
In the "Provided Matchers" section the BeFalse example has BeTrue in it:
Ω(ACTUAL).Should(BeTrue())
This has been implemented in ghttp
but needs to be documented.
I find that for a certain level fo tests it's really handy to have a "canned responses" server that understands a set of requests and has canned responses for each one. This server can then be plugged into many tests. It would be awesome if ghttp supported that. Perhaps by adding a simple mux support based on method and URI matching?
Using one of diff libraries, gomega should return a diff of 2 strings, especially handy for comparing 2 lengthy strings.
Implemented! Just adding an issue to track it.
Expect([]int{1, 2}).To(MatchElements(2, 1))
or
Expect([]int{1, 2}).To(MatchElements([]int{2, 1}))
Gophers expect to read package reference material in godoc. Move or copy some of the extensive documentation to comments as described at http://blog.golang.org/godoc-documenting-go-code.
This was originally over at onsi/ginkgo#71
The following is an extraction of a freezing test. When you run the following, Hello!!!
gets printed, but Bye!!!
does not because Expect(d.Db).To(BeNil())
freezes for no apparent reason. Go bug?
package test
import (
"database/sql"
"fmt"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
_ "github.com/mattn/go-sqlite3"
)
type Database struct {
Db *sql.DB
}
func NewSqliteDatabase(dbfile string) (*Database, error) {
db, err := sql.Open("sqlite3", dbfile)
if err != nil {
return nil, err
}
return &Database{Db: db}, nil
}
func TestFoo(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "foo")
}
var _ = Describe("Foo", func() {
var (
d *Database
)
Describe("NewSqliteDatabase()", func() {
BeforeEach(func() {
d, _ = NewSqliteDatabase("/tmp/test.sqlite3")
})
It("opens a sqlite3 database and returns *Database", func() {
fmt.Println("Hello!!!")
Expect(d.Db).To(BeNil())
fmt.Println("Bye!!!")
})
})
AfterEach(func() {
if d != nil && d.Db != nil {
d.Db.Close()
}
})
})
Expected Behavior:
$ ginkgo
Running Suite: foo
==================
Random Seed: 1400479221
Will run 1 of 1 specs
Hello!!!
• Failure [0.009 seconds]
Foo
/home/action/workspace/test/foo_test.go:53
NewSqliteDatabase()
/home/action/workspace/test/foo_test.go:46
opens a sqlite3 database and returns *Database [It]
/home/action/workspace/test/foo_test.go:45
Expected
<*sql.DB | 0xc210070c80>: { ... }
to be nil
/home/action/workspace/test/foo_test.go:43
------------------------------
Ran 1 of 1 Specs in 0.018 seconds
FAIL! -- 0 Passed | 1 Failed | 0 Pending | 0 Skipped --- FAIL: TestFoo (0.02 seconds)
FAIL
Ginkgo ran in 1.448502789s
Test Suite Failed
Actual Behavior:
$ ginkgo
test: ginkgo
Running Suite: foo
==================
Random Seed: 1400479000
Will run 1 of 1 specs
Hello!!!
^C
Ran 1 of 1 Specs in 29.979 seconds
FAIL! -- 0 Passed | 0 Failed | 0 Pending | 0 Skipped
Ginkgo ran in 31.682427676s
$ go version
go version go1.2.2 linux/amd64
$ ginkgo version
Ginkgo Version 1.0.0-beta
See here for how to handle signal-related closure:
https://code.google.com/p/go/issues/detail?id=7938
Eventually(c).Should(Receive())
has proven to be very handy...
Along similar lines,
c <- foo
is annoying in that it can block forever...
Eventually(c).Should(BeSent(foo))
could make for a nice way to handle this.
Calling
ReportAllGomegaAssertions(writer io.Writer)
Will cause Gomega to emit all assertions (regardless of pass/fail) to the passed in writer.
This was originally onsi/ginkgo#91
examples:
ssh [email protected]
password: xxxxx
or:
[Y/N?]y
Thanks.
The omega matcher interface changed with b88ba4e
The docs were partially updated and more work needs to be done here: http://onsi.github.io/gomega/#adding_your_own_matchers
Thanks for catching this @stephanos
This solves two problems:
The legacy interface requires that the Match
function return a string. This is the failure message should the result not be what the user expected. This double negative is confusing.
The legacy interface forces matchers to always render failure messages, whether the test has failed or not. While this is not, strictly speaking, a huge performance problem gomega's object formatter can - sometimes - generate race conditions. These are OK if the assertion is failing anyway but is Very Bad if the assertion is not failing.
Having explicit failure message methods allows Gomega to lazily compute these messages only if a failure has actually occurred.
My usecase is determine durations are within a certain bounds which I would find ~ useful for if it worked for ints and uints.
Was that wrong to expect the following to work?
It("works for non-blocking send", func() {
channel := make(chan bool)
go func() {
time.Sleep(100 * time.Millisecond)
// non-blocking send
select {
case channel <- true:
default:
}
}()
Eventually(channel).Should(Receive())
})
Now that I have switched and other utilities leverage build, gexec and other routines, I have noticed a proliferation of directories in my $TMPDIR that are being created but never deleted.
Most of them end up empty.
Could we have 1 root tmpdir that is used by all routines? And the ability to clean up?
The ghttp VerifyBasicAuth
handler doesn't cause a test failure if no basic auth headers were passed in the request.
It will fail a test if the wrong credentials were used, which is cool, but it'd be rather handy if it also failed when no credentials were provided.
The past participle of "occur" is "occurred," so the matcher should be HaveOccurred
. Clearly not a big deal, but it's a bit of an annoyance.
Would you prefer to leave this as-is, or should I open a PR to fix? Happy to include a small script that uses gofmt
to update client code.
When testing methods which return only an error, HaveOccurred()
doesn't read well:
Expect(MyFunc("foo")).NotTo(HaveOccurred())
I suggest an alias such as HaveFailed()
, which would produce the easier to read
Expect(MyFunc("foo")).NotTo(HaveFailed())
I suspect this is a simple change, but I'm willing to put together a pull request if desired.
Hey there,
a few months ago I wrote a wrapper around gomega called bdd. Now I recently pushed some changes to my library clock that uses 'bdd' and it suddenly a weird test failure occurs:
panic: You are trying to make an assertion, but Gomega's fail handler is nil.
If you're using Ginkgo then you probably forgot to put your assertion in an It().
Alternatively, you may have forgotten to register a fail handler with RegisterFailHandler() or RegisterTestingT().
The stacktrace:
goroutine 16 [running]:
runtime.panic(0x296840, 0xc208000d60)
/usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/panic.c:279 +0xf5
github.com/onsi/gomega.ExpectWithOffset(0x0, 0x346ba0, 0xffffffffffffff5a, 0x0, 0x0, 0x0, 0x0, 0x0)
$GOPATH/github.com/onsi/gomega/gomega_dsl.go:139 +0x8e
github.com/onsi/gomega.Expect(0x346ba0, 0xffffffffffffff5a, 0x0, 0x0, 0x0, 0x0, 0x0)
$GOPATH/github.com/onsi/gomega/gomega_dsl.go:125 +0x6f
github.com/101loops/bdd.(*Checker).run(0xc208026b70, 0x61c9b0, 0x554e00, 0xc208000b30, 0x1, 0x1, 0x2611b)
$GOPATH/github.com/101loops/bdd/checker.go:102 +0x173
github.com/101loops/bdd.Check(0x346ba0, 0xffffffffffffff5a, 0x61c9b0, 0x554e00, 0xc208000b30, 0x1, 0x1, 0x2d4)
$GOPATH/github.com/101loops/bdd/checker.go:44 +0xa7
github.com/101loops/clock.func·004()
$GOPATH/github.com/101loops/clock/clock_test.go:9 +0x1ee
github.com/onsi/ginkgo/internal/suite.(*Suite).PushContainerNode(0xc20801a6e0, 0x37bd50, 0x5, 0x4293b0, 0x0, 0x53e557, 0x47, 0x15, 0xc208010600, 0x2d4)
$GOPATH/github.com/onsi/ginkgo/internal/suite/suite.go:132 +0x1f8
github.com/onsi/ginkgo.Context(0x37bd50, 0x5, 0x4293b0, 0x0)
$GOPATH/github.com/onsi/ginkgo/ginkgo_dsl.go:285 +0x8e
github.com/101loops/bdd.Context(0x37bd50, 0x5, 0x4293b0, 0x1)
$GOPATH/github.com/101loops/bdd/spec.go:21 +0x3b
github.com/101loops/clock.func·001()
$GOPATH/github.com/101loops/clock/clock_test.go:10 +0x3e
github.com/onsi/ginkgo/internal/suite.(*Suite).PushContainerNode(0xc20801a6e0, 0x38ecd0, 0xa, 0x429398, 0x0, 0x53e557, 0x47, 0xc, 0xc20808a600, 0x1e8)
$GOPATH/github.com/onsi/ginkgo/internal/suite/suite.go:132 +0x1f8
github.com/onsi/ginkgo.Describe(0x38ecd0, 0xa, 0x429398, 0x554b80)
$GOPATH/github.com/onsi/ginkgo/ginkgo_dsl.go:256 +0x8e
github.com/101loops/bdd.Describe(0x38ecd0, 0xa, 0x429398, 0xc208012900)
$GOPATH/github.com/101loops/bdd/spec.go:12 +0x3b
github.com/101loops/clock.init()
$GOPATH/github.com/101loops/clock/clock_test.go:32 +0x82
main.init()
github.com/101loops/clock/_test/_testmain.go:48 +0x46
So I'm not sure yet why this happens now. Apparently the ginkgo.Describe
/ ginkgo.Context
are already run before the bdd.RunSpecs
(and thereby ginkgo.RunSpecs
) is run? So no failure handler could have been registered yet.
Do you know what I'm doing wrong?
Documentation at http://onsi.github.io/gomega/ is incorrect.
Description of "ConsistOf(element …interface{})" contains example that uses ContainElements() function instead of ConsistOf().
Originally from onsi/ginkgo#73
This may already be implemented, I just haven't found it.
When I have an expectation like this:
Expect(something).ToNot(BeNil())
If it fails, it logs a deep inspection of something
. I find that in many cases this leads to overwhelming output. For example, one of my structures includes a time.Time
. This is (surprisingly) over 250 of output due to a massive DST lookup table that's included in its loc
field. Some of my data structures include http or file handles that can generate thousands of lines of output (sometimes recursively, leading to hundreds of "too deep for me, man" messages).
I had assumed that I could implement Stringer or GoStringer to control the logging output, but Ginkgo doesn't seem to use these. Is there any way to get control over how complex structures are displayed?
I just spent some time debugging a silly mistake, I forgot to put an It
in my Context
, causing the fail handler to be nil and a nil-pointer dereference to occur in To()
. Maybe gomega could check that the fail handler is non-zero and panic otherwise? I guess Expect()
would be the best place?
e.g.
gexec.Interrupt([timeout])
gexec.Kill([timeout])
gexec.Signal(signal, [timeout])
Created a MatchOneOf "or matcher" for BOSH. I'd love to see something similar in Gomega.
https://github.com/cloudfoundry/bosh-agent/tree/master/matchers
Expect(ip).To(MatchOneOf(Equal("a"), Equal("b")))
I wanted to have a more englishy syntax, but Expect(ip).To(Equal("a").Or(Equal("b")))
would require matchers to return an object instead of a boolean.
This way:
Eventually(session).Should(Say("foo"))
can bail out early if the session has exited (and therefore closed the buffer) and the buffer does not contain "foo"
.
Is it intentional that time objects use deep equal to determine if two times are equivalent instead of the Equal method on the object? I could see it working either way so more curious than anything.
Expected
<time.Time>: {sec: 0, nsec: 0, loc: nil}
to equal
<time.Time>: {
sec: 0,
nsec: 0,
loc: {name: "UTC", zone: nil, tx: nil, cacheStart: 0, cacheEnd: 0, cacheZone: nil},
}
This is accomplished by gbytes
but isn't documented yet.
When trying to use gomega without ginkgo like so:
func TestMatchingIntegerWithoutGinkgo(t *testing.T) {
Expect(1).To(Equal(1))
}
func TestFailedMatchWithoutGinkgo(t *testing.T) {
Expect(1).To(Equal(2))
}
I get an invalid memory address panic instead of the message I expect.
:!go test
--- FAIL: TestFailedMatchWithoutGinkgo (0.00 seconds)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x89b25]
goroutine 5 [running]:
testing.func·004()
/usr/local/Cellar/go/1.1.1/src/pkg/testing/testing.go:348 +0xcd
github.com/onsi/gomega.(*actual).match(0x21029d0e0, 0x2102964b0, 0x21026b4d0, 0x21026b401, 0x0, ...)
/usr/local/Cellar/go/1.1.1/src/pkg/go/src/github.com/onsi/gomega/actual.go:56 +0x2d5
github.com/onsi/gomega.(*actual).To(0x21029d0e0, 0x2102964b0, 0x21026b4d0, 0x0, 0x0, ...)
/usr/local/Cellar/go/1.1.1/src/pkg/go/src/github.com/onsi/gomega/actual.go:28 +0x61
_/#{PATH}.TestFailedMatchWithoutGinkgo(0x21029e120)
/#{PATH}/main_test.go:29 +0xbf
testing.tRunner(0x21029e120, 0x1bbf90)
/usr/local/Cellar/go/1.1.1/src/pkg/testing/testing.go:353 +0x8a
created by testing.RunTests
/usr/local/Cellar/go/1.1.1/src/pkg/testing/testing.go:433 +0x86b
goroutine 1 [chan receive]:
testing.RunTests(0x13dd58, 0x1bbf60, 0x3, 0x3, 0x21029a001, ...)
/usr/local/Cellar/go/1.1.1/src/pkg/testing/testing.go:434 +0x88e
testing.Main(0x13dd58, 0x1bbf60, 0x3, 0x3, 0x1bffa0, ...)
/usr/local/Cellar/go/1.1.1/src/pkg/testing/testing.go:365 +0x8a
main.main()
_/#{PATH}/_test/_testmain.go:47 +0x9a
exit status 2
FAIL _/#{PATH} 0.055s
shell returned 1
It is very possible I'm doing something wrong (besides not using ginkgo), but it would be cool to play around with the matchers without setting up a whole ginkgo suite.
Thanks :)
var nilSlice []int
Expect(nilSlice).To(BeEmpty())
should fail. A nilSlice
is not an empty slice. For example, when JSONifying nilSlice
out comes null
instead of []
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.