Skip to main content

Ginkgo and other frameworks

Ginkgo​

Ginkgo's GinkgoTB() turns the running spec into a testing.TB. petri's helpers then work in specs as they do in plain tests, including the shared plane. Cleanups that petri registers, such as deleting the test's namespace, run when the spec ends.

suite_test.go
package ginkgo_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestSuite(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "petri with Ginkgo")
}
collection_test.go
package ginkgo_test

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"

"github.com/yyewolf/petri"
)

var _ = Describe("Owner references", func() {
var configMaps typedcorev1.ConfigMapInterface

BeforeEach(func() {
// GinkgoTB adapts the running spec to testing.TB, so petri's helpers
// work as in a plain test: the shared plane, and a namespace that is
// deleted when the spec ends.
t := GinkgoTB()
cp := petri.Start(t)
configMaps = cp.Client().CoreV1().ConfigMaps(cp.Namespace(t))
})

It("cascade to dependents", func(ctx SpecContext) {
owner, err := configMaps.Create(ctx, &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "owner"},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())

_, err = configMaps.Create(ctx, &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "dependent",
OwnerReferences: []metav1.OwnerReference{{
APIVersion: "v1", Kind: "ConfigMap", Name: owner.Name, UID: owner.UID,
}},
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())

Expect(configMaps.Delete(ctx, owner.Name, metav1.DeleteOptions{})).To(Succeed())

petri.WaitFor(GinkgoTB(), configMaps, "dependent", petri.Deleted[*corev1.ConfigMap]())
})
})

A kubebuilder suite built on envtest needs none of this: switch to the envtest drop-in and keep the suite as it is.

Without a testing.TB​

Most helpers have a variant for frameworks that cannot provide a testing.TB. It takes a context and returns an error:

With a testing.TBContext variant
petri.Start(t)petri.New(ctx), then Stop
cp.Namespace(t)cp.NewNamespace(ctx); you delete it
cp.InstallCRDs(t, ...)cp.InstallCRDsCtx(ctx, ...)
cp.InstallAdmissionWebhooks(t, ...)cp.InstallAdmissionWebhooksCtx(ctx, ...), which returns a cleanup
petri.WaitFor(t, ...)petri.WaitUntil(ctx, ...)
petri.Retry(t, ...)petri.RetryUntil(ctx, ...)
cp.AddNode(t, ...)cp.AddNodeCtx(ctx, ...); you delete it
node.Drain(t), node.Cordon(t), …node.DrainCtx(ctx), node.CordonCtx(ctx), …
cp.Bind(t, ...), cp.Evict(t, ...), …cp.BindCtx(ctx, ...), cp.EvictCtx(ctx, ...), …
cp.ExpectPod(t, ...)cp.ExpectPodCtx(ctx, ...)
cp.ExpectPods(t, ...)cp.ExpectPodsCtx(ctx, ...), then Verify(ctx)
cp.StrictPods(t)cp.StrictPodsCtx(ctx), then cp.UnexpectedPods()

The context variants leave cleanup to you. Two things need a testing.TB and have no variant: cp.EnableControllers and the shared plane. Without a testing.TB, start a dedicated plane with petri.New.