From qa-feature-flags
Wraps Flagsmith server-side SDK testing patterns: local-evaluation mode (no API calls), offline mode with LocalFileHandler + downloaded environment.json, default_flag_handler for per-feature mocked fallbacks, and the get_environment_flags / get_identity_flags evaluation paths. Use when writing tests for code using Flagsmith. Composes feature-flag-test-matrix-reference.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-feature-flags:flagsmith-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Flagsmith (open-source, also SaaS at flagsmith.com) supports
Flagsmith (open-source, also SaaS at flagsmith.com) supports three test-friendly modes per docs.flagsmith.com/clients/server-side:
environment.json snapshot; zero network.default_flag_handler.pip install flagsmith
npm install --save-dev flagsmith-nodejs
Per docs.flagsmith.com:
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)
The environment.json is downloadable via the Flagsmith CLI:
flagsmith environment-document --api-key=<server-key> --output=tests/fixtures/flagsmith-environment.json
Commit the fixture; refresh deliberately.
flagsmith = Flagsmith(
environment_key="server-key",
enable_local_evaluation=True,
environment_refresh_interval_seconds=60,
)
Local mode polls; offline mode doesn't. For tests, offline is usually preferred.
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 doesn't have the flag you're testing yet.
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="[email protected]",
traits={"plan": "premium"},
)
assert flags.is_feature_enabled("premium_feature") is True
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")
pytest tests/flagsmith/
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.
| 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 |
feature-flag-test-matrix-reference.launchdarkly-testing,
unleash-testing,
growthbook-testing.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub testland/qa --plugin qa-feature-flags