Les pages protégées par CAPTCHA interrompent les tests automatisés. CaptchaAI s'intègre à GitHub Actions pour résoudre les CAPTCHA pendant les tests CI/CD, gardant ainsi votre pipeline vert.
Flux de travail des actions GitHub
# .github/workflows/captcha-tests.yml
name: CAPTCHA Integration Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: "0 6 * * 1" # Weekly Monday 6 AM
jobs:
captcha-tests:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: pip install requests pytest
- name: Run CAPTCHA integration tests
env:
CAPTCHAAI_KEY: ${{ secrets.CAPTCHAAI_KEY }}
run: pytest tests/test_captcha.py -v --tb=short
Stocker la clé API en tant que secret GitHub
- Allez dans Paramètres → Secrets et variables → Actions
- Cliquez sur Nouveau secret du référentiel
- Nom :
CAPTCHAAI_KEY - Valeur : votre clé API CaptchaAI
- Cliquez sur Ajouter un secret
Fichier de test
# tests/test_captcha.py
import os
import time
import pytest
import requests
API_KEY = os.environ.get("CAPTCHAAI_KEY")
BASE_URL = "https://ocr.captchaai.com"
def solve_recaptcha(site_key, page_url, timeout=90):
"""Solve reCAPTCHA v2 via CaptchaAI."""
resp = requests.post(f"{BASE_URL}/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1,
}, timeout=30)
result = resp.json()
assert result.get("status") == 1, f"Submit failed: {result}"
task_id = result["request"]
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
resp = requests.get(f"{BASE_URL}/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
assert data.get("status") == 1, f"Solve failed: {data}"
return data["request"]
pytest.fail("CAPTCHA solve timed out")
@pytest.mark.skipif(not API_KEY, reason="CAPTCHAAI_KEY not set")
class TestCaptchaIntegration:
"""Integration tests for CAPTCHA-protected flows."""
def test_recaptcha_v2_solve(self):
"""Verify CaptchaAI can solve reCAPTCHA v2."""
token = solve_recaptcha(
site_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
page_url="https://www.google.com/recaptcha/api2/demo",
)
assert len(token) > 100
assert token.isascii()
def test_balance_sufficient(self):
"""Ensure account balance is enough for test suite."""
resp = requests.get(f"{BASE_URL}/res.php", params={
"key": API_KEY,
"action": "getbalance",
"json": 1,
})
balance = float(resp.json()["request"])
assert balance > 0.50, f"Low balance: ${balance}"
def test_api_key_valid(self):
"""Verify API key is accepted."""
resp = requests.get(f"{BASE_URL}/res.php", params={
"key": API_KEY,
"action": "getbalance",
"json": 1,
})
result = resp.json()
assert result.get("status") == 1, f"Invalid key: {result}"
Test matriciel (plusieurs types de CAPTCHA)
jobs:
captcha-matrix:
runs-on: ubuntu-latest
strategy:
matrix:
captcha-type: [recaptcha-v2, turnstile, image]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: pip install requests pytest
- name: Run ${{ matrix.captcha-type }} tests
env:
CAPTCHAAI_KEY: ${{ secrets.CAPTCHAAI_KEY }}
CAPTCHA_TYPE: ${{ matrix.captcha-type }}
run: pytest tests/test_${{ matrix.captcha-type }}.py -v
Mise en cache des résultats des tests
Évitez les résolutions CAPTCHA redondantes pour le code inchangé :
- name: Cache test results
uses: actions/cache@v4
with:
path: .test-cache
key: captcha-tests-${{ hashFiles('tests/**') }}
- name: Skip if cached
id: check-cache
run: |
if [ -f .test-cache/passed ]; then
echo "skip=true" >> $GITHUB_OUTPUT
fi
- name: Run tests
if: steps.check-cache.outputs.skip != 'true'
env:
CAPTCHAAI_KEY: ${{ secrets.CAPTCHAAI_KEY }}
run: |
pytest tests/test_captcha.py -v
mkdir -p .test-cache && touch .test-cache/passed
Notification Slack en cas d'échec
- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "CAPTCHA tests failed on ${{ github.ref }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "CAPTCHA tests *failed* on `${{ github.ref }}`\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Dépannage
| Problème | Parce que | Corriger |
|---|---|---|
| Les tests sautent avec "CAPTCHAAI_KEY non défini" | Secret non configuré | Ajouter un secret dans les paramètres du dépôt |
| Timeout dans CI mais fonctionne localement | Latence du réseau Runner | Augmenter le délai d'attente à 120 s |
| La vérification du solde échoue | Problème de format de clé | Vérifiez que la valeur secrète n'a pas d'espace |
| Le workflow ne s'exécute jamais | Mauvaise configuration de la branche /trigger | Vérifiez le bloc on: dans YAML |
FAQ
Combien coûte l’exécution de tests CAPTCHA dans CI ?
Une suite de tests typique résolvant 3 à 5 CAPTCHA coûte entre 0,01 et 0,03 $ par exécution. Les courses programmées hebdomadairement coûtent environ 0,10 à 0,15 $/month.
Dois-je exécuter des tests CAPTCHA sur chaque PR ?
Exécutez le solde et la validation des clés sur chaque PR. Exécutez des tests de résolution CAPTCHA complets lors de la fusion vers le principal ou selon un planning hebdomadaire pour minimiser les coûts.
Puis-je l'utiliser avec d'autres plateformes CI ?
Oui. Le code de test Python fonctionne de la même manière dans GitLab CI, CircleCI ou Jenkins. Seule la syntaxe YAML du workflow diffère.
Guides connexes
- Créer un pipeline de tests automatisés
- CAPTCHA dans les suites de tests CI
Gardez votre pipeline vert –obtenir CaptchaAIpour CI/CD.