flagsmith-testing
Wraps Flagsmith server-side SDK testing patterns (feature flags / feature toggles) so tests run without calling the Flagsmith API: offline mode with LocalFileHandler + a downloaded environment.json snapshot, local-evaluation mode (no per-request network), and default_flag_handler for per-feature mocked fallbacks, via the get_environment_flags / get_identity_flags evaluation paths. Use when writing feature-flag tests for code that uses Flagsmith, mocking flag values, or testing feature toggles offline in CI.
Install with skills.sh (any agent)
npx skills add testland/qa --skill flagsmith-testingflagsmith-testing
Overview
Flagsmith (open-source, also SaaS at flagsmith.com) supports three test-friendly modes per docs.flagsmith.com/clients/server-side (opens in new window):
Offline mode is the default choice for tests; local-evaluation and default_flag_handler detail live in references/flagsmith-modes.md.
When to use
How to use
Offline mode with LocalFileHandler
Per docs.flagsmith.com (opens in new window):
from flagsmith import Flagsmith
from flagsmith.offline_handlers import LocalFileHandler
local_file_handler = LocalFileHandler(environment_document_path="tests/fixtures/flagsmith-environment.json")
flagsmith = Flagsmith(offline_mode=True, offline_handler=local_file_handler)Download the environment.json via the Flagsmith CLI, then commit it (refresh deliberately):
flagsmith environment-document --api-key=<server-key> --output=tests/fixtures/flagsmith-environment.jsonEvaluate flags
def test_environment_flag():
flags = flagsmith.get_environment_flags()
assert flags.is_feature_enabled("secret_button") is False
assert flags.get_feature_value("secret_button") == '{"colour": "#b8b8b8"}'
def test_identity_flag():
flags = flagsmith.get_identity_flags(
identifier="user@example.com",
traits={"plan": "premium"},
)
assert flags.is_feature_enabled("premium_feature") is TrueIntegrity test - the same identity must resolve consistently:
def test_same_identity_consistent():
f1 = flagsmith.get_identity_flags("u1")
f2 = flagsmith.get_identity_flags("u1")
assert f1.is_feature_enabled("flag-x") == f2.is_feature_enabled("flag-x")CI integration
jobs:
flagsmith-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- run: pip install flagsmith
- run: pytest tests/flagsmith/No env vars needed in offline mode.
Worked example
A service reads a secret_button flag (boolean plus a JSON colour value) and a premium_feature flag gated on a plan trait, tested fully offline:
Result: pytest tests/flagsmith/ runs green in CI with zero network access and no analytics pollution.
References
Flagsmith test modes, anti-patterns, and limitations
View source (opens in new window)Flagsmith test modes, anti-patterns, and limitations
Deeper detail for flagsmith-testing (opens in new window). Offline mode (covered in the skill spine) is the default for tests; the modes below are secondary.
Local-evaluation mode
Polls the Flagsmith API periodically and evaluates flags locally between refreshes (no per-request network, but not zero network):
flagsmith = Flagsmith(
environment_key="server-key",
enable_local_evaluation=True,
environment_refresh_interval_seconds=60,
)Local mode polls; offline mode does not. For tests, offline is usually preferred.
default_flag_handler - per-flag mock
Programmatic fallback used when the offline environment.json does not have the flag under test yet:
from flagsmith import Flagsmith
from flagsmith.models import DefaultFlag
def default_flag_handler(feature_name: str) -> DefaultFlag:
if feature_name == "secret_button":
return DefaultFlag(enabled=False, value='{"colour": "#b8b8b8"}')
return DefaultFlag(enabled=False, value=None)
flagsmith = Flagsmith(
environment_key="test-key",
default_flag_handler=default_flag_handler,
)Useful when the offline environment.json does not have the flag you are testing yet.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Production env_key in tests | Real API calls + analytics pollution | offline_mode + LocalFileHandler |
| environment.json not committed | Test flakes when prod changes | Commit; refresh deliberately |
| Mixing offline_mode + local_evaluation_mode | Conflicting; one takes precedence | Pick one |
| default_flag_handler returns DefaultFlag with no value | Tests for value-based flags fail silently | Always set value |
Skipping flagsmith.get_identity_flags for identity-scoped tests | Bypasses per-user logic | Use identity API |
| Per-test new Flagsmith client | Slow init | Session-scoped fixture |
Limitations
Related skills
feature-flag-test-matrix-reference
Pure-reference catalog of feature-flag test matrix design. Defines the flag-state combinatorics problem (N flags × M variants × K user-segments = N×M×K test cases), the canonical coverage strategies (pairwise interaction coverage; default-only smoke; full matrix; risk-driven matrix), the kill-switch + percentage-rollout test patterns, and the relationship between flags + experiments (flags toggle behaviour; experiments measure outcome). Use when designing the flag-test surface for a new project or auditing existing flag-test coverage.
flag-removal-runbook-author
Workflow-driven skill that builds the runbook for safely removing a feature flag from the codebase + the flag platform. Walks through: pre-removal verification (flag fully rolled out, no usage variance in evaluations, dependent code paths identified), the code-removal steps (delete the if-branches, simplify, restore types), the platform-side removal (archive in LaunchDarkly / Unleash / Flagsmith / GrowthBook), the verification post-removal, and the rollback plan. Use when removing a flag that has finished its mission (rollout-complete, experiment-shipped, kill-switch retired).
flag-state-coverage-builder
Workflow-driven skill that builds a flag-state coverage matrix from the project's flag inventory and risk register. Walks through: inventorying flags (grep for flag-evaluation calls), classifying each (boolean / multi-variant / kill-switch / experiment), choosing the coverage strategy (per-flag-isolation / pairwise / full / risk-driven per feature-flag-test-matrix-reference), generating the test matrix (PICT for pairwise; manual for risk-driven), and emitting test skeletons. Use when introducing flag-test coverage to a new codebase or when a flag-related incident exposes a coverage gap.
growthbook-testing
Wraps GrowthBook Node SDK testing patterns: GrowthBookClient initialization with direct payload (initSync; no network), isOn / getFeatureValue / evalFeature, scoped instances (createScopedInstance) for per-request user context, inline experiment (runInlineExperiment) tests, and tracking-callback assertion patterns. Use when writing tests for code using GrowthBook for flags + experiments.
killswitch-test-author
Workflow-driven skill that authors the four test categories specific to kill-switch (ops-toggle) flags: switch-OFF graceful degradation, fail-static default when the flag service is unreachable, latency budget for the kill decision, and no-data-corruption mid-flight. Distinct from flag-state-coverage-builder (which builds a full coverage matrix across all flag types) and feature-flag-test-matrix-reference (which catalogs patterns without producing tests). Use when a kill-switch flag exists in the codebase and needs dedicated, production-incident-rehearsing tests authored for it.
launchdarkly-testing
Wraps LaunchDarkly server-side SDK testing patterns: TestData data source for hermetic tests (no network), file-based data source for fixture-driven tests, flag override patterns (TestData.update for per-test flag values), and assignment-integrity tests. Use when writing tests for code that uses LaunchDarkly flags.
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. Use when writing tests for code that resolves feature flags through the OpenFeature SDK regardless of the underlying flag management platform.
unleash-testing
Wraps Unleash (Open Source / SaaS) SDK testing patterns: bootstrap with a static toggles array (no network), the test mode (disableMetrics + disablePolling), the custom strategy testing pattern (implement a Strategy class + assert isEnabled), and assignment-integrity tests. Use when writing tests for code that uses Unleash for feature flags.