Dieser Leitfaden führt Sie durch einen A/B-Test, der zwei Varianten eines Checkout-Flows in einer mobilen App vergleicht. Die primäre Metrik ist die Sitzungsdauer (Sekunden); die sekundäre Metrik ist die Anzahl der abgeschlossenen Schritte.
Experimentdaten
// Variant A (control): original checkout flow
val controlDurationSec = doubleArrayOf(
34.2, 41.5, 38.7, 45.1, 36.9, 42.3, 39.8, 44.6, 37.4, 40.1,
43.2, 35.8, 41.9, 38.3, 46.0, 39.5, 42.7, 37.1, 40.8, 44.3
)
// Variant B (treatment): simplified checkout flow
val treatmentDurationSec = doubleArrayOf(
29.1, 33.8, 31.5, 35.2, 28.7, 32.4, 30.9, 34.6, 29.8, 33.1,
31.2, 27.5, 34.0, 30.3, 36.1, 31.8, 33.5, 28.9, 32.7, 35.8
)
Schritt 1: Beide Gruppen zusammenfassen
val controlSummary = controlDurationSec.describe()
val treatmentSummary = treatmentDurationSec.describe()
controlSummary.mean // control average
treatmentSummary.mean // treatment average
controlSummary.standardDeviation // control spread
treatmentSummary.standardDeviation // treatment spread
Schritt 2: Annahmen prüfen
Normalität
val controlNormality = shapiroWilkTest(controlDurationSec)
val treatmentNormality = shapiroWilkTest(treatmentDurationSec)
controlNormality.pValue
treatmentNormality.pValue
Varianzhomogenität
val variances = leveneTest(controlDurationSec, treatmentDurationSec)
variances.pValue
Schritt 3: Test auswählen und durchführen
// Welch's t-test (default: equalVariances = false)
val result = tTest(controlDurationSec, treatmentDurationSec)
result.statistic
result.pValue
result.confidenceInterval // 95% CI for the difference in means
result.isSignificant() // true if p < 0.05
Wenn der Levene-Test gleiche Varianzen bestätigt hat:val equalVar = tTest(
controlDurationSec,
treatmentDurationSec,
equalVariances = true
)
equalVar.pValue
val result = mannWhitneyUTest(controlDurationSec, treatmentDurationSec)
result.statistic
result.pValue
result.isSignificant()
Einseitige Tests
Wenn Sie erwarten, dass die Behandlung die Sitzungsdauer verkürzt:
val oneSided = tTest(
controlDurationSec,
treatmentDurationSec,
alternative = Alternative.GREATER // control > treatment
)
oneSided.pValue
Schritt 4: Zweite Metrik testen
Wenden Sie denselben Workflow auf die sekundäre Metrik an.
// Number of completed checkout steps per session
val controlSteps = doubleArrayOf(
3.0, 4.0, 3.0, 5.0, 3.0, 4.0, 4.0, 5.0, 3.0, 4.0,
4.0, 3.0, 4.0, 3.0, 5.0, 4.0, 4.0, 3.0, 4.0, 5.0
)
val treatmentSteps = doubleArrayOf(
5.0, 5.0, 4.0, 5.0, 5.0, 5.0, 4.0, 5.0, 5.0, 5.0,
4.0, 5.0, 5.0, 4.0, 5.0, 5.0, 5.0, 4.0, 5.0, 5.0
)
// Discrete step counts are typically non-normal
shapiroWilkTest(controlSteps).pValue
val stepsResult = mannWhitneyUTest(controlSteps, treatmentSteps)
stepsResult.pValue
stepsResult.isSignificant()
Schritt 5: Korrelation zwischen Metriken
Prüfen Sie, ob die beiden Metriken innerhalb jeder Gruppe zusammenhängen.
// Within the treatment group: do faster sessions correlate with more completed steps?
val correlation = spearmanCorrelation(treatmentDurationSec, treatmentSteps)
correlation.coefficient // negative means shorter sessions correlate with more steps
correlation.pValue
Spearman-Korrelation wird hier bevorzugt, da eine der Metriken (Schritte) ordinal ist.
Gepaarter Vorher/Nachher-Vergleich
Wenn dieselben Nutzer vor und nach einer Änderung gemessen werden, verwenden Sie gepaarte Tests.
val beforeMs = doubleArrayOf(
340.2, 415.0, 387.1, 451.3, 369.5, 423.8, 398.0, 446.2, 374.1, 401.5
)
val afterMs = doubleArrayOf(
310.5, 380.2, 355.8, 410.7, 335.1, 392.4, 365.3, 405.9, 340.8, 371.6
)
val paired = pairedTTest(beforeMs, afterMs)
paired.pValue
paired.confidenceInterval
// Non-parametric alternative
val wilcoxon = wilcoxonSignedRankTest(beforeMs, afterMs)
wilcoxon.pValue