CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/experiment-sdk-testing

Umbrella for experimentation-SDK test harnesses: the shared offline-datafile / hermetic-init pattern (commit a point-in-time flag/experiment config fixture, initialize the SDK with no network, pin arms per test, assert assignment integrity), with per-vendor references for Statsig (localMode + overrideGate), Optimizely (datafile + forced decisions), Split.io / Harness FME (localhost mode + features map or YAML fixture), Amplitude Experiment (local evaluation + bootstrap), and VWO (settings file + deterministic bucketing). Use when writing tests for application code instrumented with any of these five experimentation SDKs; for experiment DESIGN gates use ab-test-validity-checklist, and to read results use experiment-results-interpreter.

76

Quality

96%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

vwo.mdreferences/

VWO SDK testing

The VWO (Visual Website Optimizer) server-side SDK uses a settings file (equivalent to Optimizely's datafile) for offline-capable testing. Per developers.vwo.com, the SDK supports multiple languages with a common API: activate, get_feature_variable_value, is_feature_enabled, track, push.

When to use

  • Tests for code that reads a VWO feature variable / experiment.
  • Force-bucketing for per-test assignment pinning.
  • Assignment-integrity tests per ab-test-validity-checklist Step 3.

Authoring

Install

pip install vwo-python-sdk
npm install --save-dev vwo-node-sdk

Settings-file-based init

import json
import vwo

with open("tests/fixtures/vwo-settings.json") as f:
    settings = json.load(f)

client = vwo.launch(settings, is_development_mode=True)

is_development_mode=True disables event tracking to VWO servers - fully-offline tests.

Activate an experiment / variation

def test_get_variation_for_user():
    variation_name = client.activate("checkout-experiment", "user-1")
    assert variation_name in ("Control", "Variation-1")

Feature variable

def test_feature_variable_value():
    value = client.get_feature_variable_value("checkout-experiment", "button_color", "user-1")
    assert value in ("blue", "green")

Force-bucket a user

VWO doesn't have a direct "force decision" API like Optimizely; the canonical approach is to construct user IDs that hash into specific buckets - or use the SDK's userPreSegment callback where supported.

Per VWO docs, the bucketing is deterministic on the user ID. Tests rely on this:

def test_specific_user_id_in_treatment():
    # User IDs are bucketed deterministically; pre-compute and pin
    KNOWN_TREATMENT_USER = "test-user-treatment-12345"
    variation = client.activate("checkout-experiment", KNOWN_TREATMENT_USER)
    assert variation == "Variation-1"

A pre-test step generates user IDs and records their bucket assignments in a fixture; tests reference the fixture.

Assignment integrity tests

def test_same_user_always_same_variation():
    v1 = client.activate("expt", "user-1")
    v2 = client.activate("expt", "user-1")
    assert v1 == v2

def test_bucketing_is_uniform():
    counts = {"Control": 0, "Variation-1": 0}
    for i in range(10000):
        v = client.activate("expt", f"user-{i}")
        if v: counts[v] += 1
    # 50/50 split → within a few percent
    ratio = counts["Variation-1"] / sum(counts.values())
    assert 0.48 < ratio < 0.52

The bucketing-uniformity test is also a unit-level SRM check per ab-test-validity-checklist Step 2.

Event tracking

def test_conversion_tracked():
    client.activate("expt", "user-1")
    success = client.track("expt", "user-1", "checkout_completed")
    assert success

Running

pytest tests/vwo/

CI integration

jobs:
  vwo-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v5
      - run: pip install vwo-python-sdk
      - run: pytest tests/vwo/

Anti-patterns

Anti-patternWhy it failsFix
Live-mode tests with real accountPollutes prod analyticsis_development_mode=True
Settings-file not committedTests flake on schema changesCommit fixture; refresh deliberately
User IDs that hash into one bucket onlyFalse sense of "covering both arms"Verify via bucketing-uniformity test
Skipping conversion-tracking testTrack-event regressions silentTest track() success
Different settings files in dev vs CIBehaviour divergesSingle fixture
Tests not isolated per experimentCross-experiment bucketing leakPer-test client teardown

Limitations

  • No direct force-decision API. Must rely on deterministic bucketing or modify the user pre-segmentation.
  • Settings file is point-in-time. Drift between fixture + prod invisible.
  • Bucketing-uniformity tests need many user IDs. Below 1000 iterations the variance dominates.
  • Event tracking is fire-and-forget in offline mode. Can't assert delivery; only the local-call success.

References

  • VWO Python SDK: github.com/wingify/vwo-python-sdk.
  • VWO developer docs: developers.vwo.com.
  • Companion: ab-test-validity-checklist; result-trust references (peeking, guardrails) live in experiment-results-interpreter.
  • Sibling vendor references: statsig.md, optimizely.md, split-io.md, amplitude.md.

SKILL.md

tile.json