Skip to content
Agentmart
Submit a tool

ginkgo-testing

Ginkgo/Gomega testing patterns for Konflux — test cleanup (envtest), Eventually/Consistently soft assertions, and helper conventions.

Skill by konflux-ci

IndexedApache-2.0★ 215
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/konflux-ci-ginkgo-testing

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Ginkgo/Gomega testing patterns for Konflux — test cleanup (envtest), Eventually/Consistently soft assertions, and helper conventions. Use when writing or reviewing Ginkgo tests.

Use cases: testing, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/ginkgo-testing

What's inside

Skill name
ginkgo-testing
Description
Ginkgo/Gomega testing patterns for Konflux — test cleanup (envtest), Eventually/Consistently soft assertions, and helper conventions. Use when writing or reviewing Ginkgo tests.
License
Apache-2.0
Instructions
72 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Ginkgo / Gomega Testing Patterns

## When to use this skill

This skill applies **after** you have determined that Ginkgo/Gomega is the correct framework for the code you are writing or reviewing. Framework selection follows a locality rule (see AGENTS.md § Code Style): (1) match the existing file, (2) match neighboring files, (3) default to Ginkgo/Gomega only when no established style exists. Do not use this skill to justify converting packages that use testify, `testing.T`+Gomega, or plain table tests to Ginkgo.

## Test cleanup in envtest

envtest has no garbage collector — deleted parent CRs do not cascade-delete their children. Two cleanup patterns handle this:

- **`DeferCleanupParentAndChildren`** — for tests involving **cluster-scoped** children (ClusterRole, ClusterRoleBinding, VWC, MWC, ConsoleLink, SCC). Deletes parent first (stopping reconciles), then explicitly deletes orphaned children. **Never** register separate `DeferCleanup` calls for parent and cluster-scoped children — Ginkgo's LIFO ordering will delete children first while the reconciler is still active, causing flaky timeouts.
- **`DeferCleanup(testutil.DeleteAndWait, ...)`** — for tests that only need to clean up the parent CR (no cluster-scoped children). Stale namespaced children are harmless: the next test's reconcile updates their ownerReferences to the new parent via `SetControllerReference` in `ApplyOwned`.

```go
// Cluster-scoped children: use DeferCleanupParentAndChildren
Expect(k8sClient.Create(ctx, parentCR)).To(Succeed())
testutil.DeferCleanupParentAndChildren(k8sClient, parentCR,
    &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: "child-role"}},
    &rbacv1.ClusterRoleBinding{ObjectMeta: metav1.ObjectMeta{Name: "child-binding"}},
)

// Namespaced-only children: simple DeferCleanup is sufficient
Expect(k8sClient.Create(ctx, parentCR)).To(Succeed())
DeferCleanup(testutil.DeleteAndWait, k8sClient, parentCR)
```

## Eventually / Consistently and soft assertions

Inside `Eventually` or `Consistently` callbacks, **never** use global `Expect()` — it triggers a hard Ginkgo panic that aborts the callback immediately, preventing `Eventually` from retrying. Instead, use the `func(g Gomega)` callback signature and call `g.Expect()` for soft failures that let `Eventually` retry on the next poll.

Any helper function called inside an `Eventually` block must accept a `Gomega` parameter and use `g.Expect()` internally. See `echoGetG` in `test/go-tests/proxy_test.go` for a real example.

```go
// ✗ Wrong — global Expect() panics on failure, Eventually cannot retry
Eventually(func() {
    resp := echoGet(url)
    Expect(resp.StatusCode).To(Equal(200))
}).Should(Succeed())

// ✓ Correct — g.Expect() signals failure softly, Eventually retries
Eventually(func(g Gomega) {
    resp := echoGetG(g, url)
    g.Expect(resp.StatusCode).To(Equal(200))
}).Should(Succeed())
```

## Kubernetes API error assertions

When asserting that a resource does not exist, use `apierrors.IsNotFound()` — never match error strings:

```go
// ✗ Wrong — brittle, breaks across K8s versions
g.Expect(k8sClient.Get(ctx, nn, obj)).To(MatchError(ContainSubstring("not found")))

// ✓ Correct — uses typed status code
err := k8sClient.Get(ctx, nn, obj)
g.Expect(apierrors.IsNotFound(err)).To(BeTrue(), "unexpected error: %v", err)
```

Import via `apierrors "k8s.io/apimachinery/pkg/api/errors"` (some files import the package without an alias and call `errors.IsNotFound()` — both work, but `apierrors` avoids confusion with the standard `errors` package).

The same principle applies to other typed API error checks — prefer `apierrors.IsAlreadyExists()`, `apierrors.IsConflict()`, etc. over string matching.

## CRD self-healing and drift tests

For `Watches(&CRD{}, MapCRDToRequest)` tests:

1. **Labels** — assert both `KonfluxOwnerLabel` and `KonfluxComponentLabel` on recreated CRDs, in the initial wait and again after recreation.
2. **Cleanup** — `DeferCleanup(testutil.DeleteAndWait, k8sClient, cr)` for CRD-only tests (each table entry uses a different CRD name, so no LIFO risk). Use `DeferCleanupParentAndChildren` only when the controller also creates other cluster-scoped children (ClusterRole, ClusterRoleBinding, VWC, MWC, etc.).
3. **Entry descriptions** — use `c.kind` in `DescribeTable` entries. Use `c.name` (FQDN) when the controller has multiple CRDs with the same Kind (e.g. imagecontroller).

From konflux-ci/konflux-ci, Apache-2.0.

More from konflux-ci/konflux-ci

Signals

Stars
215
Forks
169
Open issues
96
Last commit (this folder)
Sep 22, 2026 (1 month ago)
Last release
Sep 7, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from konflux-ci

Cite this page

ginkgo-testing skill. Agent Mart. https://agentmart.dev/skills/konflux-ci-ginkgo-testing (last updated 2026-10-24)