Skip to main content

AI-powered diagnostic for Playwright test failures — ~600 lines replace 23K lines of MCP

Project description

🚀 QA Autopilot

Plugin pytest — Diagnostic IA des échecs Playwright en temps réel

Python Playwright OpenAI pytest License Lines


InstallationQuick StartScorecardComment ça marcheConfiguration


🎯 Le problème

Un test Playwright échoue. Le message d'erreur dit :

TimeoutError: Page.click: Timeout 5000ms exceeded.
waiting for locator("a[href='/international/']")

Le sélecteur est bon. L'élément existe. Alors pourquoi ça marche pas ?

Parce que le bandeau cookies recouvre tout. Ou parce que l'élément est dans un iframe. Ou parce que le DOM a été rechargé en AJAX. Ou parce que le bouton est disabled. Ou parce que tu fais un click() au lieu d'un dblclick().

QA Autopilot diagnostique la vraie cause en une seule commande.


📊 Scorecard

Résultats sur une suite de 7 tests pièges conçus pour piéger les outils de diagnostic :

Test Piège Diagnostic IA Catégorie Confiance
🫣 Overlay cookies Élément recouvert par bandeau ✅ Bandeau cookies bloque le click element_obscured 🟢 95%
🖼️ Iframe invisible Élément dans iframe, cherché dans main frame ✅ Contexte iframe manquant iframe_context 🟢 95%
👻 Stale AJAX Locator capturé avant rechargement DOM ✅ Référence obsolète après AJAX stale_reference 🟢 95%
↪️ Redirect silencieux URL redirigée 301/302 ✅ Test PASSED (piège détecté)
🚫 Bouton disabled Élément visible mais disabled ✅ Attribut disabled détecté element_disabled 🟢 95%
🔤 Regex Unicode Zinedine vs Zinédine ✅ Mismatch accent dans regex encoding_mismatch 🟢 95%
🫣 Double-click Consent manager intercepte le click ✅ Overlay détecté element_obscured 🟢 95%

6/6 diagnostics corrects à 95% de confiance — le 7ème test PASSED (pas de diagnostic nécessaire).


⚠️ Limitations

[!CAUTION] Tests de +200 lignes : le contexte envoyé à l'IA est volontairement tronqué. Un test E2E doit rester court — un scénario, une responsabilité, moins de 50 lignes. Au-delà, c'est un problème de conception, pas de diagnostic. Refactorisez vos tests avant de chercher la cause d'un échec.

📦 Installation

pip install qa-autopilot

Ou depuis les sources :

git clone https://github.com/jmer-consulting/qa-autopilot.git
cd qa-autopilot
pip install -e .

Prérequis

pip install playwright openai
playwright install chromium

Variable d'environnement

export OPENAI_API_KEY=sk-...

⚡ Quick Start

Mode pytest (recommandé)

Ajoute un seul flag à ta commande pytest :

pytest tests/ --qa-autopilot -v

C'est tout. Chaque test en échec reçoit un diagnostic IA automatique.

Avec rapport HTML

pytest tests/ --qa-autopilot --html=qa-reports/rapport.html --self-contained-html -v

Mode standalone

python -m qa_autopilot tests/test_checkout.py
python -m qa_autopilot tests/test_login.py::test_auth
python -m qa_autopilot tests/ -k "checkout" --headed

Mode import direct

from qa_autopilot import QAInterceptor

# Dans ton test
interceptor = QAInterceptor(page)
interceptor.start()

# ... ton test ...

# En cas d'échec
diagnosis = interceptor.diagnose(error_message, "test_file.py")
print(diagnosis["root_cause"])
print(diagnosis["category"])

🔍 Comment ça marche

┌─────────────────────────────────────────────────────┐
│                    TON TEST PLAYWRIGHT               │
│                                                      │
│   page.goto("https://example.com")                  │
│   page.click("#submit")           ← FAIL            │
│   expect(page).to_have_url(...)                     │
└──────────────────────┬──────────────────────────────┘
                       │
         ┌─────────────▼─────────────┐
         │    QA AUTOPILOT HOOK      │
         │   (écoute en parallèle)   │
         └─────────────┬─────────────┘
                       │
    ┌──────────────────┼──────────────────┐
    ▼                  ▼                  ▼
┌────────┐      ┌──────────┐      ┌───────────┐
│  DOM   │      │ RÉSEAU   │      │ CONSOLE   │
│Listener│      │ Capture  │      │ Capture   │
│  (JS)  │      │ req/res  │      │ err/warn  │
└───┬────┘      └────┬─────┘      └─────┬─────┘
    │                │                   │
    └────────────────┼───────────────────┘
                     │
         ┌───────────▼───────────┐
         │   BUNDLE CONTEXTE     │
         │  code + erreur + DOM  │
         │  + réseau + console   │
         │  + screenshot (opt)   │
         └───────────┬───────────┘
                     │
         ┌───────────▼───────────┐
         │    UN PROMPT → IA     │
         │   (12 catégories)     │
         │   diagnostic + fix    │
         └───────────┬───────────┘
                     │
    ┌────────────────┼────────────────┐
    ▼                ▼                ▼
┌────────┐    ┌───────────┐    ┌──────────┐
│Terminal│    │   JSON    │    │  Jira    │
│ Output │    │  Report   │    │ (si bug) │
└────────┘    └───────────┘    └──────────┘

Pipeline en 5 étapes

  1. Hook transparent — Se branche sur la page Playwright via les events natifs
  2. Capture en parallèle — DOM (listener JS injecté), réseau, console, screenshots
  3. Détection d'échec — Le hook pytest intercepte le FAILED
  4. Bundle + Prompt — Tout le contexte part en UN appel IA
  5. Diagnostic — Cause racine + catégorie + fix concret + rapport JSON

🏷️ Les 12 catégories de diagnostic

Icône Catégorie Description
🎯 wrong_selector Sélecteur cassé, inexistant ou trop large
⏭️ missing_step Étape manquante (cookies, goto, dropdown)
⏱️ timing Race condition, élément pas encore prêt
🫣 element_obscured Élément recouvert par overlay/modal/bannière
🚫 element_disabled Élément trouvé mais désactivé
🔀 wrong_action Mauvaise méthode (click vs dblclick, fill vs type)
🖼️ iframe_context Élément cherché dans le mauvais frame
🔤 encoding_mismatch Problème Unicode/accents/regex
👻 stale_reference Locator obsolète après changement DOM
📊 test_data Assertion avec mauvaise valeur attendue
🐛 app_bug Bug applicatif (pas le test) → génère un ticket Jira
🌐 network Requêtes réseau en échec (4xx/5xx)

⚙️ Configuration

Variables d'environnement

Variable Défaut Description
OPENAI_API_KEY (obligatoire) Clé API OpenAI
QA_MODEL gpt-4.1-mini Modèle IA à utiliser
QA_SCREENSHOT 0 1 pour inclure les screenshots dans le prompt
QA_REPORT_DIR qa-reports/ Dossier des rapports

Arguments pytest

pytest tests/ --qa-autopilot          # Active le diagnostic IA
pytest tests/ --qa-autopilot --headed # Avec navigateur visible
pytest tests/ --qa-autopilot -k "login" # Filtrer par keyword

📁 Structure des rapports

qa-reports/
├── summary_20260223_014751.json       # Rapport consolidé du run
├── diag_test_casse_20260223_014713.json  # Diagnostic individuel
├── diag_test_casse_20260223_014659.json
├── jira_test_casse_20260223_014659.md    # Ticket Jira (si app_bug)
└── rapport.html                          # Rapport HTML pytest

Exemple de rapport consolidé

[
  {
    "test": "test_element_cache_par_overlay[chromium]",
    "category": "element_obscured",
    "confidence": 0.95,
    "root_cause": "L'élément ciblé est recouvert par le bandeau cookies",
    "suggested_fix": "Fermer le bandeau cookies avant de cliquer"
  }
]

🏗️ Architecture

qa-autopilot/
├── qa_autopilot/
│   ├── __init__.py          # Exports publics
│   ├── core.py              # QAInterceptor + capture
│   ├── prompt.py            # Prompt v2 (12 catégories)
│   ├── diagnose.py          # Appel IA + retry + JSON mode
│   ├── reporter.py          # Rapports JSON + Jira markdown
│   ├── listener.js          # DOM listener (injection navigateur)
│   └── plugin.py            # Hooks pytest
├── tests/
│   ├── test_casse.py        # Suite de tests pièges
│   └── conftest.py
├── examples/
│   └── standalone.py        # Exemple d'utilisation directe
├── pyproject.toml
├── LICENSE
└── README.md

Note : La version actuelle est un fichier monolithique qa_autopilot.py (~600 lignes). Le découpage ci-dessus est la cible pour la v2.


🆚 Pourquoi pas les alternatives ?

QA Autopilot Playwright MCP (23K lignes) SaaS (Testim, Mabl...)
Lignes de code ~600 23 000+ Fermé
Installation pip install MCP server + config Compte + licence
Config 1 flag 32 outils MCP Dashboard + intégration
Prix Gratuit + clé OpenAI Gratuit 200-500€/mois/user
Diagnostic 12 catégories, 95% Basique Variable
Vendor lock-in Zéro MCP protocol Total

🛠️ DOM Listener — Cascade 6 tiers

Le listener JavaScript injecté dans le navigateur utilise une cascade de sélecteurs en 6 niveaux, du plus stable au moins stable :

Tier Stratégie Exemple
1 data-testid / id / name [data-testid="submit-btn"]
2 aria-label / placeholder / title [aria-label="Fermer"]
3 href (liens) a[href="/checkout"]
4 Parent avec attribut stable [data-testid="form"] button
5 Label associé (inputs) //label[contains(text(),"Email")]//input
6 CSS court + nth-of-type button.primary:nth-of-type(2)

Chaque sélecteur est validé pour son unicité dans le DOM. Support Shadow DOM inclus.


📄 License

MIT — Fais-en ce que tu veux.


Créé par Julien Mer — JMer Consulting

QA Architect · 20+ ans d'expérience · Katalon Top Partner Europe

Newsletter QA OPS LAB

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qa_autopilot-1.0.0.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qa_autopilot-1.0.0-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file qa_autopilot-1.0.0.tar.gz.

File metadata

  • Download URL: qa_autopilot-1.0.0.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.2

File hashes

Hashes for qa_autopilot-1.0.0.tar.gz
Algorithm Hash digest
SHA256 7cd041b01b1f32e3327c5300c69c89d742bed7a473991f2c1693471331e4729a
MD5 46e624285d5bba44246a4163af7d0dc2
BLAKE2b-256 1a8454d59d20a57e8f202397f7de6c4e4219134968727a2e5b0430a043174be5

See more details on using hashes here.

File details

Details for the file qa_autopilot-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: qa_autopilot-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.2

File hashes

Hashes for qa_autopilot-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5afe16d64f024ac4a43a971c6a0497525f55df492d95c667927a25c2192351ff
MD5 edd5c844cd33de83ef1cb5751c02e491
BLAKE2b-256 1b78c888a877206ce478a2d070fe3caddac6b4a50831cfce8a7a1773f3fb132c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page