AccueilBlogTest technique A/B testing rigoureux : statistiques pour les décisions data
Guide recrutement data

Test technique A/B testing rigoureux : statistiques pour les décisions data

Les A/B tests mal conduits mènent à de mauvaises décisions business. En entretien Senior, on évalue la rigueur statistique : puissance, significativité, erreurs classiques.

Data Builder·Juin 2025·7 min de lecture·Data Scientist · Data Analyst
Sommaire
  1. Fondements du test A/B
  2. Calcul de la puissance
  3. Erreurs de type I et II
  4. Quels tests statistiques
  5. Pièges classiques
  6. Interpréter les résultats
  7. Grille

1Fondements du test A/B

Question discriminante

Quels sont les prérequis pour conduire un A/B test rigoureux ?

  • Hypothèse claire — 'changer la couleur du bouton CTA de gris en orange augmente le taux de clic de 5%'. Une seule hypothèse testée à la fois
  • Métrique primaire — définir UNE métrique principale avant de lancer. Pas 10 métriques 'par sécurité'
  • Randomisation — assigner les utilisateurs aléatoirement. Jamais par semaine paire/impaire ou par région
  • Isolation — pas d autres changements pendant le test. Un test A/B contaminé donne des résultats inutilisables
  • Durée minimale — laisser tourner au moins 2 semaines pour capturer les effets cycliques (semaine vs week-end)

2Calculer la taille d échantillon

Question discriminante

Comment calculez-vous la taille d échantillon nécessaire avant de lancer un A/B test ?

from scipy import stats from statsmodels.stats.power import TTestIndPower import numpy as np # Paramètres du test baseline_rate = 0.05 # taux de conversion actuel : 5% min_detectable_effect = 0.01 # on veut détecter +1pp (5% -> 6%) alpha = 0.05 # risque d erreur de type I (5%) power = 0.80 # puissance souhaitée (80%) # Calcul de la taille d échantillon pour un test de proportion from statsmodels.stats.proportion import proportion_effectsize effect_size = proportion_effectsize(baseline_rate, baseline_rate + min_detectable_effect) analysis = TTestIndPower() n = analysis.solve_power( effect_size=effect_size, alpha=alpha, power=power, alternative='two-sided' ) print(f'Taille par groupe : {int(np.ceil(n))} utilisateurs') # Si 1000 visites/jour -> durée = 2 * ceil(n) / 1000 jours

3Erreurs de type I et II

Question discriminante

Quelle est la différence entre l erreur de type I et l erreur de type II ? Comment les contrôlez-vous ?

ErreurDéfinitionProbabilitéContrôle
Type I (faux positif)Déclarer un effet qui n existe pasα (niveau de significativité)Fixer α = 0.05 avant le test
Type II (faux négatif)Rater un vrai effetβ = 1 - puissanceTaille d échantillon suffisante

Analogie : α = condamner un innocent. β = laisser libre un coupable. Les deux sont des erreurs, mais de natures différentes. En A/B testing business, β = rater une amélioration réelle.

4Choisir le bon test statistique

Question discriminante

Quel test statistique utilisez-vous selon la métrique testée ?

from scipy import stats import numpy as np # Test de proportion (taux de clic, taux de conversion) from statsmodels.stats.proportion import proportions_ztest count = np.array([150, 180]) # conversions A et B nobs = np.array([3000, 3000]) # visiteurs A et B stat, pvalue = proportions_ztest(count, nobs) # Test t (panier moyen, durée de session) stat, pvalue = stats.ttest_ind(group_a['revenue'], group_b['revenue']) # Test U de Mann-Whitney (non paramétrique, si non-normal) stat, pvalue = stats.mannwhitneyu(group_a['revenue'], group_b['revenue']) # Chi-carré (variables catégorielles) contingency = np.array([[450, 550], [480, 520]]) # [A: conv/non-conv, B] chi2, pvalue, dof, expected = stats.chi2_contingency(contingency) print(f'p-value: {pvalue:.4f}') print(f'Résultat: {"Significatif" if pvalue < 0.05 else "Non significatif"}')

5Pièges classiques du A/B testing

Question discriminante

Quelles sont les erreurs les plus fréquentes dans les A/B tests ?

  • Peeking problem — arrêter le test dès que p < 0.05 sans attendre la taille d échantillon prévue. Multiplie les faux positifs par 3-5x
  • Multiple comparisons — tester 10 métriques et prendre la plus significative. Correction de Bonferroni nécessaire : α/n
  • Sample ratio mismatch — si le groupe B a 45% des utilisateurs au lieu de 50%, la randomisation est cassée. Vérifier avant d analyser
  • Novelty effect — les utilisateurs cliquent plus sur une nouveauté. Attendre 2+ semaines
  • Network effects — les utilisateurs du groupe A et B interagissent (réseaux sociaux, plateformes de partage). Unité d expérimentation incorrecte

6Interpréter les résultats

Question discriminante

Comment présentez-vous les résultats d un A/B test à des stakeholders non statisticiens ?

  • Éviter 'statistiquement significatif' — dire plutôt 'nous sommes à 95% confiants que le changement a un effet réel'
  • Intervalle de confiance — 'la vraie amélioration est entre +0.5% et +2.3% avec 95% de confiance' est plus utile qu une p-value seule
  • Significativité pratique — une amélioration de +0.1% peut être statistiquement significative mais trop petite pour justifier le déploiement
  • Décision business — présenter les résultats en termes de revenus projetés : '+1.2% de conversion = +45 000€/mois'
import scipy.stats as stats import numpy as np # Test de significativite statistique def ab_test_significance(control_conversions, control_n, treatment_conversions, treatment_n): p_control = control_conversions / control_n p_treatment = treatment_conversions / treatment_n # Test proportion z p_pool = (control_conversions + treatment_conversions) / (control_n + treatment_n) se = np.sqrt(p_pool * (1-p_pool) * (1/control_n + 1/treatment_n)) z_score = (p_treatment - p_control) / se p_value = 2 * (1 - stats.norm.cdf(abs(z_score))) return { 'p_value': p_value, 'z_score': z_score, 'significant': p_value < 0.05, 'relative_lift': (p_treatment - p_control) / p_control } # Calcul de la taille d echantillon minimale def sample_size_needed(baseline_rate, mde=0.1, alpha=0.05, power=0.8): from statsmodels.stats.power import zt_ind_solve_power effect_size = mde * baseline_rate / np.sqrt(baseline_rate * (1-baseline_rate)) n = zt_ind_solve_power(effect_size=effect_size, alpha=alpha, power=power) return int(np.ceil(n))
  • Significativite statistique 95% - p-value < 0.05 ne signifie pas que le test est concluant. Il faut aussi une taille d echantillon suffisante et un effet minimal detectable defini a l avance
  • MDE (Minimum Detectable Effect) - definir avant le test l effet minimal que vous voulez detecter. MDE 1% sur un taux de 5% = 4 fois plus d echantillons qu un MDE de 2%
  • Biais de peeking - arreter le test des que p < 0.05 augmente le taux de faux positifs. Definir la duree a l avance et ne pas y toucher
  • Multi-armed bandit - alternative aux A/B tests classiques. Alloue dynamiquement plus de trafic vers la variante gagnante. Thompson Sampling ou UCB
  • Metriques guardrail - definir des metriques de securite (latence, taux d erreur, revenus par user) qui ne doivent pas degrader meme si la metrique primaire s ameliore

7Grille par niveau

NiveauMaitriseSignal GONO-GO
ConfirméTest t et z, p-value, alpha, randomisationCalcule la taille d échantillon avant le test, sait choisir entre test t et zArrête le test dès que p < 0.05 (peeking)
SeniorPuissance, erreurs type I/II, multiple comparisons, interprétation businessCalcule la puissance, corrige pour les comparaisons multiples, présente en termes businessNe sait pas ce qu est la puissance statistique

Vous recrutez un Data Scientist ou Data Analyst ?

Premier entretien gratuit. Rapport GO/NO-GO sous 48h.