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. Use when writing tests for code that resolves feature flags through the OpenFeature SDK regardless of the underlying flag management platform.
79
99%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Companion reference for openfeature-sdk-testing. The SKILL.md spine
shows the full TypeScript/Node.js flow; the flow is identical here,
only the API names differ.
Install (Maven, per github.com/open-feature/java-sdk README):
<dependency>
<groupId>dev.openfeature</groupId>
<artifactId>sdk</artifactId>
<version>1.20.2</version>
</dependency>Configure the InMemoryProvider:
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.providers.memory.Flag;
import dev.openfeature.sdk.providers.memory.InMemoryProvider;
Map<String, Flag<?>> flags = new HashMap<>();
flags.put("show-new-ui", Flag.builder()
.variant("on", true)
.variant("off", false)
.defaultVariant("on")
.build());
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(new InMemoryProvider(flags));
Client client = api.getClient();Evaluate flags:
boolean enabled = client.getBooleanValue("show-new-ui", false);
FlagEvaluationDetails<Boolean> details =
client.getBooleanDetails("show-new-ui", false);
// details.getValue() - resolved value
// details.getVariant() - "on" or "off"
// details.getReason() - "STATIC", "DEFAULT", etc.
// details.getErrorCode()- ErrorCode.FLAG_NOT_FOUND, TYPE_MISMATCH, etc.Per-invocation evaluation context:
Map<String, Value> attrs = new HashMap<>();
attrs.put("email", new Value("user@example.com"));
EvaluationContext ctx = new ImmutableContext("user-42", attrs);
boolean value = client.getBooleanValue("beta-access", false, ctx);Install (per github.com/open-feature/python-sdk README):
pip install openfeature-sdk==0.10.0Configure the InMemoryProvider:
from openfeature import api
from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider
flags = {
"show-new-ui": InMemoryFlag(
default_variant="on",
variants={"on": True, "off": False}
),
}
api.set_provider_and_wait(InMemoryProvider(flags))
client = api.get_client()Evaluate flags:
enabled = client.get_boolean_value("show-new-ui", False)
details = client.get_boolean_details("show-new-ui", False)
# details.value - resolved value
# details.variant - "on" / "off"
# details.reason - "STATIC", "DEFAULT", etc.
# details.error_code - "FLAG_NOT_FOUND", "TYPE_MISMATCH", etc.Per-invocation evaluation context:
from openfeature.evaluation_context import EvaluationContext
ctx = EvaluationContext(targeting_key="user-42",
attributes={"email": "user@example.com"})
details = client.get_boolean_details("beta-access", False, ctx)Per the OpenFeature specification
(openfeature.dev/specification/sections/flag-evaluation,
Requirements 1.4.3-1.4.15), EvaluationDetails carries:
| Field | Type | Meaning |
|---|---|---|
value | T | Resolved flag value (spec req. 1.4.3) |
flagKey | string | The requested flag identifier (1.4.5) |
variant | string | Provider-supplied variant name (1.4.6) |
reason | string | Resolution rationale (1.4.7) |
errorCode | enum | Failure classification (1.4.8) |
errorMessage | string | Optional context for the error (1.4.13) |
flagMetadata | map | Immutable provider-supplied data (1.4.14) |
Canonical reason values (per
openfeature.dev/specification/sections/providers,
Requirement 2.2.5):
STATIC, DEFAULT, TARGETING_MATCH, SPLIT, CACHED,
DISABLED, UNKNOWN, STALE, ERROR.
Canonical error codes include FLAG_NOT_FOUND, TYPE_MISMATCH,
PARSE_ERROR, TARGETING_KEY_MISSING, INVALID_CONTEXT, GENERAL,
PROVIDER_NOT_READY, PROVIDER_FATAL.
Per openfeature.dev/docs/reference/concepts/hooks and the specification (openfeature.dev/specification/sections/hooks, Requirement 4.3.1-4.3.8), the four stages are:
| Stage | Runs when |
|---|---|
before | Before flag resolution; can modify evaluation context |
after | After successful resolution; can validate the returned value |
error | On resolution failure or unhandled before-hook error |
finally | Unconditionally after all other stages |
Execution order for before: API - Client - Invocation. For after,
error, finally: reverse order (Invocation - Client - API), per
specification Requirement 4.4.2.