LaunchDarkly测试

testland2026-10-25查看 999复制 1414

封装 LaunchDarkly 服务端 SDK 测试模式:用于封闭式测试的 TestData 数据源(无网络)、用于夹具驱动测试的基于文件的数据源、开关覆盖模式(用 TestData.update 设置逐测试的开关值)以及赋值完整性测试。适用于为使用 LaunchDarkly 开关的代码编写测试;至于这些测试首先应覆盖哪些开关组合,参见 feature-flag-test-matrix-reference。

Download (.md)

📘如何使用这个技能

  1. 1
    复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
  2. 2
    打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
  3. 3
    粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
  4. 4
    直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景

💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。

SKILL.md5904 chars
---
name: launchdarkly-testing
description: "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; to decide which flag combinations those tests should cover in the first place, see feature-flag-test-matrix-reference."
---

# launchdarkly-testing

## Overview

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](https://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.

## When to use

- Unit / integration tests for code that calls
  `client.variation()` / `client.boolVariation()`.
- Tests asserting on targeting-rule behaviour (segment matching,
  percentage rollout).
- Assignment-integrity tests per `ab-test-validity-checklist`.

## Authoring

### Install

```bash
npm install --save-dev launchdarkly-node-server-sdk
pip install launchdarkly-server-sdk
```

### Initialize with TestData

```typescript
import * 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));
```

### Variation evaluation

```typescript
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);
});
```

### Targeting rules

```typescript
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);
});
```

### Percentage rollout (deterministic assignment)

```typescript
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);
});
```

### File-based data source (alternative)

For fixture-shared tests:

```typescript
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.

### Teardown

```typescript
afterAll(async () => {
  await client.close();
});
```

## Running

```bash
npm test
```

## CI integration

```yaml
jobs:
  ld-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
      - run: npm ci && npm test
```

No `LAUNCHDARKLY_SDK_KEY` needed in CI - TestData/file source
replaces it.

## Anti-patterns

| 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 |

## Limitations

- **TestData is server-side-SDK-specific.** Client-side SDKs
  have their own offline modes.
- **Doesn't validate LaunchDarkly's UI-side rollout math.**
  Platform-side bucketing is separately tested.
- **No experiment-results validation.** That's
  `feature-flag-experiment-validator` (in the qa-shift-right plugin).
- **`FileDataSource` schema is LaunchDarkly-internal.** Refer
  to LD docs for the format.

## References

- LaunchDarkly SDK docs:
  [launchdarkly.com/docs/sdk](https://launchdarkly.com/docs/sdk).
- TestData data source guide:
  [launchdarkly.com/docs/sdk/features/test-data-sources](https://launchdarkly.com/docs/sdk/features/test-data-sources).
- File-based data source:
  [launchdarkly.com/docs/sdk/features/flags-from-files](https://launchdarkly.com/docs/sdk/features/flags-from-files).
- Deciding WHICH flag combinations to cover is a separate step this skill does
  not do: when code branches on several flags, load
  `feature-flag-test-matrix-reference` for the matrix, then come back here to
  pin each flag's value per test.
- Sibling SDK umbrella:
  `openfeature-sdk-testing` (OpenFeature + Unleash / Flagsmith / GrowthBook
  references).
- Cross-plugin:
  `feature-flag-test-harness`,
  `ab-test-validity-checklist`.
来源:skillsdirectory

评论0

登录后参与评论

还没有评论,来抢沙发吧