Use whenever code that reads LaunchDarkly feature flags needs tests: the TestData source for hermetic tests with no network, file-based fixtures, per-test flag overrides and assignment checks. Which flag combinations to cover is in openfeature-sdk-testing's flag test-matrix reference.
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
The canonical home for this skill is testland/launchdarkly-testing
LaunchDarkly's server-side SDK exposes a TestData data source
that lets tests configure flag values without any network call -
the canonical hermetic-test pattern. Per
launchdarkly.com/docs/sdk,
TestData replaces the production data source; everything else
about the SDK (variation evaluation, targeting rules, default
handling) runs the real code paths.
client.variation() / client.boolVariation().ab-test-validity-checklist.npm install --save-dev launchdarkly-node-server-sdk
pip install launchdarkly-server-sdkimport * as LaunchDarkly from 'launchdarkly-node-server-sdk';
const td = LaunchDarkly.TestData.dataSource();
const client = LaunchDarkly.init('sdk-test-key', {
updateProcessor: td,
sendEvents: false, // No event uploads in tests
});
await client.waitForInitialization();
// Configure a flag's default + per-user variation
td.update(td.flag('show-new-ui').booleanFlag().on(true));test('flag on returns true', async () => {
td.update(td.flag('show-new-ui').booleanFlag().on(true));
const user = { key: 'user-1' };
const enabled = await client.variation('show-new-ui', user, false);
expect(enabled).toBe(true);
});
test('flag off returns default', async () => {
td.update(td.flag('show-new-ui').booleanFlag().on(false));
const enabled = await client.variation('show-new-ui', { key: 'user-1' }, false);
expect(enabled).toBe(false);
});test('only premium users get treatment', async () => {
td.update(
td.flag('premium-feature')
.booleanFlag()
.variationForUser('premium-user-1', true)
.fallthroughVariation(false)
);
expect(await client.variation('premium-feature', { key: 'premium-user-1' }, false)).toBe(true);
expect(await client.variation('premium-feature', { key: 'free-user-1' }, false)).toBe(false);
});test('rollout is deterministic per user', async () => {
td.update(td.flag('half-rollout').booleanFlag().on(true).variations(true, false));
// Bucketing is deterministic on user key
const r1 = await client.variation('half-rollout', { key: 'user-1' }, false);
const r2 = await client.variation('half-rollout', { key: 'user-1' }, false);
expect(r1).toBe(r2);
});For fixture-shared tests:
const fileSource = LaunchDarkly.FileDataSource({
paths: ['./tests/fixtures/ld-flags.json'],
});
const client = LaunchDarkly.init('sdk-test-key', {
updateProcessor: fileSource,
sendEvents: false,
});The JSON file uses LaunchDarkly's flag-snapshot format. Useful for cross-language test fixtures.
afterAll(async () => {
await client.close();
});npm testjobs:
ld-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- run: npm ci && npm testNo LAUNCHDARKLY_SDK_KEY needed in CI - TestData/file source
replaces it.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Real SDK key in tests | Test traffic pollutes prod analytics | TestData / FileDataSource |
sendEvents: true in tests | Event upload from CI | sendEvents: false |
| Multiple init per test | Slow init; leaks | One global client; TestData.update per test |
Asserting exact variation result without td.update | Race vs SDK state | Always update first |
Forgetting await client.waitForInitialization() | Race; variation returns default | Always wait |
Sharing td across test files | Cross-test pollution | Per-file or per-test TestData |
No teardown client.close() | Network handles leak | Always close in afterAll |
experiment-results-interpreter.FileDataSource schema is LaunchDarkly-internal. Refer
to LD docs for the format.openfeature-sdk-testing (its flag test-matrix reference) for the matrix, then come back here to
pin each flag's value per test.openfeature-sdk-testing (OpenFeature + Unleash / Flagsmith / GrowthBook
references).feature-flag-test-harness,
ab-test-validity-checklist.testland/qa
aa16752
Canonical home
since Jul 23, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.