
Tables And Dynamic Specs
Parameterize and generate Ginkgo specs, DescribeTable/Entry table-driven specs, Entry...
Install
npx skills add onsi/ginkgo --skill tables-and-dynamic-specs -g -a claude-code -y- Repository
- onsi/ginkgo9.1k
- Category
- Engineering
- Updated
- 26d ago
- License
- MIT
- Context cost
- Mediumabout 1,858 tokens
- Runs scripts
- No, instructions only
What it does
Parameterize and generate Ginkgo specs, DescribeTable/Entry table-driven specs, Entry descriptions (string, nil, closure, EntryDescription), PEntry/FEntry and per-Entry decorators, DescribeTableSubtree, generating specs in a construction-time loop, loading fixtures in TestXxx before RunSpecs, and shared-behavior closures. Use when you have repetitive specs differing only by inputs, want data-driven or generated specs, or are extracting reusable It blocks across Contexts.
Table specs and dynamically generated specs
Ginkgo gives you a DSL for table-driven specs plus idioms for generating specs from loops and data. All of it is syntactic sugar that runs during the tree-construction phase (ginkgo:overview), the gotchas all follow from that.
Perfer DescrtibeTable/DescribeTableSubtree with shared configuration over multiple repeated Its.
Docs: https://onsi.github.io/ginkgo/#table-specs.
DescribeTable + Entry
DescribeTable(desc, specFunc, ...Entry) generates one container holding one It per Entry. Entry(desc, params...), its params are passed to specFunc at run time and must match specFunc's signature (you get a clear runtime message if they don't).
DescribeTable("Extracting the author's first and last name",
func(author string, isValid bool, firstName, lastName string) {
book := &books.Book{Title: "My Book", Author: author, Pages: 10}
Expect(book.IsValid()).To(Equal(isValid))
Expect(book.AuthorFirstName()).To(Equal(firstName))
Expect(book.AuthorLastName()).To(Equal(lastName))
},
Entry("both names", "Victor Hugo", true, "Victor", "Hugo"),
Entry("one name", "Hugo", true, "", "Hugo"),
Entry("no name", "", false, "", ""),
)
A DescribeTable is just a container, so nest it inside Describe/Context and surround it with BeforeEach, setup runs fresh before each entry's spec.
THE gotcha: Entry params are evaluated at construction time
Entry(...) arguments are evaluated when the tree is built, before any BeforeEach has run. So an Entry cannot read a variable initialized in BeforeEach; it will see the zero value (a nil map/pointer).
var shelf map[string]*books.Book
BeforeEach(func() { shelf = loadShelf() }) // runs at RUN time
// WRONG, shelf is nil when Entry is evaluated at construction time
DescribeTable("category", func(b *books.Book, c books.Category) { ... },
Entry("novel", shelf["Les Miserables"], books.CategoryNovel), // nil pointer!
)
