本文へ移動
cccskills
無料GitHub で公開

openfeature-sdk-testing

Wraps OpenFeature (CNCF vendor-neutral SDK abstraction) testing patterns: the InMemoryProvider for hermetic tests without network calls, provider registration via OpenFeature.setProvider, the getBooleanValue/getBooleanDetails evaluation API with EvaluationDetails (value, variant, reason, errorCode), hooks for evaluation side-effects, and evaluation context for targeting-rule tests. Covers TypeScript, Java, and Python SDKs, plus per-vendor hermetic-bootstrap references for Unleash (bootstrap toggles), Flagsmith (offline LocalFileHandler), and GrowthBook (initSync payload). Use when writing tests for code that resolves feature flags through the OpenFeature SDK or the Unleash / Flagsmith / GrowthBook native SDKs; LaunchDarkly has its own skill (launchdarkly-testing).

日本語の概要は準備中です。原文の説明を表示しています。

testland/qaスター 13(GitHub 13 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(7)

  • SKILL.md11.9 KB
  • .tessl-plugin/plugin.json914 B
  • references/flagsmith-modes.md2.2 KB
  • references/flagsmith.md4.7 KB
  • references/growthbook.md5.1 KB
  • references/multi-language-and-spec.md4.8 KB
  • references/unleash.md4.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

openfeature-sdk-testing

Overview

The OpenFeature SDK ships an InMemoryProvider in every language that substitutes real flag-management infrastructure with in-process flag state, letting unit and integration tests run without any network call. The production evaluation path (targeting logic, type coercion, defaults) is exercised in full; only the data source is swapped. Per openfeature.dev/docs/reference/concepts/provider, "an application integrator can register one provider at a time."

Scope: this skill is the SDK-testing umbrella. The body covers the vendor-neutral OpenFeature layer teams adopt to keep application code decoupled from a specific provider; the vendor-native hermetic-bootstrap patterns (each an offline data-source variant of the same idea) live in references/: references/unleash.md (bootstrap toggles + custom strategies), references/flagsmith.md (offline LocalFileHandler + default_flag_handler), and references/growthbook.md (initSync payload + inline experiments). LaunchDarkly's TestData source has enough distinct surface for its own skill: launchdarkly-testing.

When to use

  • Tests for code that calls client.getBooleanValue() / get_boolean_value() through the OpenFeature SDK, regardless of which provider runs in production.
  • Tests asserting on evaluation details: variant name, reason code, or error code (e.g., FLAG_NOT_FOUND, TYPE_MISMATCH).
  • Tests that inject hook logic (telemetry, validation) exercised during flag evaluation.
  • Teams migrating between flag providers who want tests that survive the swap.
  • Assignment-integrity tests per ab-test-validity-checklist.

How to use

TypeScript/Node.js is the canonical language below. The Java and Python flow is identical; only the API names differ, listed in references/multi-language-and-spec.md.

TypeScript / Node.js

Install (per github.com/open-feature/js-sdk README):

npm install --save @openfeature/server-sdk

Configure the InMemoryProvider with flag variants and a default variant:

import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk';

const flags = {
  'show-new-ui': {
    variants: { on: true, off: false },
    disabled: false,
    defaultVariant: 'on',
  },
  'checkout-v2': {
    variants: { enabled: true, disabled: false },
    disabled: false,
    defaultVariant: 'disabled',
  },
} as const;

await OpenFeature.setProvider(new InMemoryProvider(flags));
const client = OpenFeature.getClient();

Evaluate flags using the typed evaluation API (per openfeature.dev/docs/reference/concepts/evaluation-api):

// Returns the resolved value; falls back to default on error
const enabled = await client.getBooleanValue('show-new-ui', false);

// Returns full EvaluationDetails
const details = await client.getBooleanDetails('show-new-ui', false);
// details.value    - the resolved boolean
// details.variant  - e.g. "on"
// details.reason   - e.g. "STATIC", "DEFAULT", "TARGETING_MATCH"
// details.errorCode- e.g. "FLAG_NOT_FOUND" when the flag is absent

Typical test pattern:

import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk';

describe('checkout feature', () => {
  let client: Client;

  beforeAll(async () => {
    await OpenFeature.setProvider(new InMemoryProvider({
      'checkout-v2': {
        variants: { enabled: true, disabled: false },
        disabled: false,
        defaultVariant: 'disabled',
      },
    }));
    client = OpenFeature.getClient();
  });

  afterAll(() => OpenFeature.close());

  it('returns false when flag defaults to disabled', async () => {
    const value = await client.getBooleanValue('checkout-v2', false);
    expect(value).toBe(false);
  });

  it('returns details with reason STATIC for static flags', async () => {
    const details = await client.getBooleanDetails('checkout-v2', false);
    expect(details.reason).toBe('STATIC');
  });

  it('returns FLAG_NOT_FOUND error code for unknown flag', async () => {
    const details = await client.getBooleanDetails('unknown-flag', false);
    expect(details.errorCode).toBe('FLAG_NOT_FOUND');
  });
});

Java and Python install/configure/evaluate blocks live in references/multi-language-and-spec.md.

EvaluationDetails and reason codes

EvaluationDetails carries value, flagKey, variant, reason, errorCode, errorMessage, and flagMetadata. Canonical reason values include STATIC, DEFAULT, TARGETING_MATCH, SPLIT, CACHED, DISABLED, UNKNOWN, STALE, ERROR; canonical error codes include FLAG_NOT_FOUND, TYPE_MISMATCH, TARGETING_KEY_MISSING, and PROVIDER_NOT_READY. The full field table with spec requirement numbers is in references/multi-language-and-spec.md.

Evaluation context for targeting-rule tests

Evaluation context is "a container for arbitrary contextual data that can be used as a basis for dynamic evaluation" (per openfeature.dev/docs/reference/concepts/evaluation-context). The targeting key is a unique identifier (user ID, session ID) that providers use for deterministic bucketing. Custom attributes carry additional data (email, plan, region).

Context can be set at three levels: global (via the API object), client, and per invocation. Lower levels override duplicate keys from higher levels.

// TypeScript - per-invocation context for targeting-rule tests
const ctx = { targetingKey: 'user-42', email: 'user@example.com' };
const details = await client.getBooleanDetails('beta-access', false, ctx);
expect(details.reason).toBe('TARGETING_MATCH');

Java and Python context builders (ImmutableContext, EvaluationContext) are in references/multi-language-and-spec.md.

Hooks for test-time side-effects

Hooks intercept the flag evaluation lifecycle at four stages - before (can modify evaluation context), after (validate the returned value), error (on resolution failure), and finally (unconditionally). The stage table and execution order (per specification Requirement 4.4.2) are in references/multi-language-and-spec.md.

Register hooks at global, client, or invocation level:

// Global hook - runs for every flag evaluation
OpenFeature.addHooks({
  before(ctx) {
    // ctx carries flagKey, flagValueType, defaultValue, evaluationContext
    console.log(`Evaluating ${ctx.flagKey}`);
  },
  after(ctx, details) {
    // details is the EvaluationDetails for this evaluation
    expect(details.errorCode).toBeUndefined();
  },
  error(ctx, err) {
    console.error(`Flag ${ctx.flagKey} failed: ${err.message}`);
  },
});

Test use case: attach an after hook to assert that no evaluation returns an error code, surfacing FLAG_NOT_FOUND regressions across the entire test run without asserting each flag individually.

Anti-patterns

Anti-patternWhy it failsFix
Registering a real (networked) provider in unit testsNetwork calls; non-deterministic; slowInMemoryProvider for unit tests
Evaluating without setProviderAndWait / await setProviderReturns default with PROVIDER_NOT_READY error code before initAlways await provider readiness
Sharing a single InMemoryProvider instance across test filesCross-test state pollutionCreate a fresh provider per describe block
Asserting only value; ignoring reason and errorCodeHides fallback-to-default failures (flag absent, type mismatch)Assert details.reason and details.errorCode explicitly
Testing provider internals (variant weighting, targeting logic)That is the provider's responsibility, not the application'sTest what the application does with the evaluated value
Omitting OpenFeature.close() in teardownLeaks provider state and background threadsAlways call close() / shutdown() in afterAll

Limitations

  • InMemoryProvider does not replicate production targeting rules. To test that a real provider evaluates a segment correctly, write an integration test against that provider's native test harness - launchdarkly-testing, or the vendor references in references/ (unleash.md, flagsmith.md, growthbook.md).
  • Client-side OpenFeature SDKs (@openfeature/web-sdk) use a different setContext pattern; this skill targets server-side SDKs.
  • Hook before stages can modify the evaluation context in some SDK versions but the specification marks this as optional behavior - verify against your SDK version.
  • InMemoryProvider does not fire PROVIDER_CHANGED events on putIfAbsent in all SDK versions; check release notes when relying on event-driven updates in tests.

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Builds a CI gate that fails the build on **new** WCAG / a11y violations introduced by a PR while grandfathering pre-existing violations on a per-rule / per-page baseline. Aggregates verdicts from axe-core / pa11y / Lighthouse a11y / WAVE / IBM Equal Access scans. Use when a project has accumulated a11y debt and a strict "zero violations" gate would block every PR - the ratchet pattern lets the team ship while preventing regressions.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Workflow skill that builds an A/B-test validity checklist from an experiment proposal, walking the canonical design-correctness gates - pre-registered OEC/power/guardrails, randomization unit + SRM check, assignment integrity, telemetry, peeking discipline, novelty/primacy, post-experiment SRM re-check - into a per-experiment checklist + sign-off form. Use when launching, auditing, or governing an experiment. For pitfall mechanics (guardrails, peeking) see experiment-results-interpreter's references; to read an already-valid result use experiment-results-interpreter; for per-SDK harness tests use experiment-sdk-testing - this gates DESIGN, not SDK code.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

The single install-flow skill: the reference contract for the PWA install flow (installability gate fields, `beforeinstallprompt` handshake, per-platform paths - Android WebAPK / iOS Share menu / Firefox no-op - and the `display-mode` post-install signal, in references/install-flow-reference.md) plus the build-an-X workflow that emits the Add-to-Home-Screen suite. Walks the four-stage timeline, emitting one test per gate cell per [web.dev/articles/install-criteria][install-criteria], the deferred-prompt → `prompt()` → `userChoice` chain per [web.dev/articles/customize-install][customize-install], the iOS Safari manual-metadata branch (`apple-touch-icon`) per [web.dev/learn/pwa/installation][learn-pwa], and the post-install `(display-mode: standalone)` MQ assertion. Output: a Playwright spec with per-stage cells plus a coverage matrix. Use when a PWA's manifest, icons, or install handler change, when install conversion drops at an unknown stage, or when triaging a flaky install assertion.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Build-an-X workflow that uses an LLM to map existing tests to spec sections - given a spec doc + the test suite, the LLM identifies which tests cover which sections, surfaces uncovered sections (gap), and recommends specific tests to add. Output is a coverage matrix per spec ID. Scope is mapping tests that already exist and naming the gaps, not authoring tests for new acceptance criteria. Use when a spec doc and a test suite both exist but nobody can say which requirements are actually covered - before a release sign-off, an audit, or a decision about where to spend the next round of test effort.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Generates tests from natural-language specs (acceptance criteria, user stories, requirements) using an LLM, with confidence scoring per test case (LLM self-assessment plus heuristics: assertion quality, naming, completeness), batching uncertain cases for human review, and integration with the team's existing test framework. Use when the user asks to generate unit tests from acceptance criteria, convert user stories to test cases, automate test creation from requirements, or augment a spec-driven test suite with AI-generated stubs that are then curated before merge.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Configures Allure Report (test-runner adapter install, `allure-results` directory wiring, `categories.json` for failure classification, `history-trend.json` retention via the copy-history-between-runs pattern), runs the Allure CLI to convert `allure-results` to a static HTML site, and uploads the report as a CI artifact. Use when the team needs richer test reporting than JUnit XML - step-level attachments, per-test history, retry tracking, and severity / epic / feature labeling across framework-agnostic adapters (pytest, Jest, JUnit, TestNG, NUnit, Mocha). As a rich static HTML report generator, it is the open-source alternative to the sunset ExtentReports (JVM/.NET per-test HTML narrative); for hosted cross-run flakiness analytics rather than a static per-run report use currents-integration.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

testland のスキルをすべて見る

このスキルの問題を報告する