Closed plastikfan closed 1 year ago
hey there - you can use DescribeTable
for such usecases but the documentation is a bit buried: https://pkg.go.dev/github.com/onsi/ginkgo/v2#Entry
DescribeTable("async",
func(ctx SpecContext, entry *asyncTE) {
defer leaktest.Check(GinkgoT())()
//use entry in here to configure this particular test
var wg sync.WaitGroup
path := helpers.Path(root, "RETRO-WAVE")
optionFn := func(o *nav.TraverseOptions) {
o.Store.Subscription = nav.SubscribeFolders
o.Store.DoExtend = true
o.Callback = asyncCallback("WithCPUPool/primary session")
o.Notify.OnBegin = begin("🛡️")
}
session := &nav.PrimarySession{
Path: path,
OptionFn: optionFn,
}
_, err := session.Init().WithCPUPool().Run(&nav.AsyncInfo{
Ctx: ctx,
Wg: &wg,
JobsChanOut: jobsChOut,
OutputsChOut: outputsChIn,
})
wg.Wait()
Expect(err).To(BeNil())
},
func(entry *asyncTE) string {
return fmt.Sprintf("%s ===> given: '%v'", entry.should, entry.given)
},
Entry(nil, &asyncTE{
given: "WithCPUPool",
should: "run with context",
}),
)
You don't call It
within the body of the table function. It becomes the body of the It
. Instead, just as with It
, you can have it take a SpecContext
as a first argument and Ginkgo will treat it like an It
that accepts a SpecContext
.
You can then decorate individual entries with SpecTimeout
and NodeTimeout
if you want to control the timeouts for each entry. Also - while you certainly can create a custom type like asyncTE
I tend to just pass arguments in if there are fewer than ~a few:
DescribeTable("async",
func(ctx SpecContext, given string, should string) {
defer leaktest.Check(GinkgoT())()
//use entry in here to configure this particular test
var wg sync.WaitGroup
path := helpers.Path(root, "RETRO-WAVE")
optionFn := func(o *nav.TraverseOptions) {
o.Store.Subscription = nav.SubscribeFolders
o.Store.DoExtend = true
o.Callback = asyncCallback("WithCPUPool/primary session")
o.Notify.OnBegin = begin("🛡️")
}
session := &nav.PrimarySession{
Path: path,
OptionFn: optionFn,
}
_, err := session.Init().WithCPUPool().Run(&nav.AsyncInfo{
Ctx: ctx,
Wg: &wg,
JobsChanOut: jobsChOut,
OutputsChOut: outputsChIn,
})
wg.Wait()
Expect(err).To(BeNil())
},
func(given string, should string) string {
return fmt.Sprintf("%s ===> given: '%v'", should, given)
},
Entry(nil, "WithCPUPool", "run with context", SpecTimeout(time.Minute)), //e.g.
)
Finally - I noticed you were using the contents of asyncTE
to control the name of the test I've updated the example above to show how to do that since DescribeTable
doesn't allow a nested It
.
Thanks @onsi, your tips worked a treat, just what I was looking for and some nice bonuses, 🙏
I currently have a set of It based unit tests which look like this:
But since I have a few of test unit tests which look very similar, I want to turn them into a table based test suite. As I started coding up the table, I realised I didnt have a context, which then led me to wonder, well how do I specify a context input param to a DescribeTable test suite.
I did a check with chatgpt, which ended up creating an example that failed at runtime. The table looked something like this:
The ginkgo error was:
So it looks like the It can't be used in this way.
So what is the solution to this, or can't we use DescribeTable for test cases that require a context? (I have looked in the documentation and I can't see any examples that cover this scenario).