Use Cases

Xử lý CAPTCHA trong thử nghiệm tích hợp liên tục

Chạy thử nghiệm toàn diện đối với các trang được bảo vệ bằng CAPTCHA trong quy trình CI/CD của bạn — không cần can thiệp thủ công.


Vấn đề

Đường ống CI/CD chạy tự động. CAPTCHA yêu cầu sự tương tác của con người. Nếu không có dịch vụ giải quyết, các bài kiểm tra toàn diện của bạn sẽ không thành công mỗi khi đạt được CAPTCHA.

Giải pháp: Sử dụng API của CaptchaAI trong bộ thử nghiệm của bạn. Khóa API được lưu trữ dưới dạng bí mật CI và các thử nghiệm sẽ tự động giải quyết CAPTCHA trong quá trình thực thi quy trình.


Kiến trúc

┌──────────────┐     ┌──────────────┐     ┌────────────┐     ┌──────────────┐
│ Git Push     │────▶│ CI Runner    │────▶│ E2E Tests  │────▶│ Test Report  │
│              │     │ (headless    │     │ + CAPTCHA  │     │              │
│              │     │  Chrome)     │     │ solving    │     │              │
└──────────────┘     └──────────────┘     └────────────┘     └──────────────┘
                                                │
                                                ▼
                                         ┌────────────┐
                                         │ CaptchaAI  │
                                         │ API        │
                                         └────────────┘

Người trợ giúp kiểm tra

import os
import time
import requests

class CICaptchaSolver:
    """CAPTCHA solver designed for CI environments."""
    BASE = "https://ocr.captchaai.com"

    def __init__(self):
        self.api_key = os.environ.get("CAPTCHAAI_API_KEY")
        if not self.api_key:
            raise EnvironmentError("CAPTCHAAI_API_KEY not set")

    def solve(self, params, initial_wait=10, timeout=120):
        params["key"] = self.api_key
        params["json"] = 1
        resp = requests.post(f"{self.BASE}/in.php", data=params).json()
        if resp["status"] != 1:
            raise Exception(f"CAPTCHA submit failed: {resp['request']}")

        task_id = resp["request"]
        time.sleep(initial_wait)
        deadline = time.time() + timeout

        while time.time() < deadline:
            result = requests.get(
                f"{self.BASE}/res.php",
                params={"key": self.api_key, "action": "get", "id": task_id, "json": 1},
            ).json()
            if result["request"] == "CAPCHA_NOT_READY":
                time.sleep(5)
                continue
            if result["status"] == 1:
                return result["request"]
            raise Exception(f"CAPTCHA solve failed: {result['request']}")

        raise TimeoutError("CAPTCHA solve timed out in CI")

    def solve_recaptcha(self, sitekey, pageurl):
        return self.solve({
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": pageurl,
        })

    def solve_turnstile(self, sitekey, pageurl):
        return self.solve({
            "method": "turnstile",
            "sitekey": sitekey,
            "pageurl": pageurl,
        })

tích hợp pytest

conftest.py

import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

@pytest.fixture(scope="session")
def captcha_solver():
    return CICaptchaSolver()

@pytest.fixture(scope="function")
def browser():
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--disable-gpu")
    driver = webdriver.Chrome(options=options)
    driver.set_window_size(1920, 1080)
    yield driver
    driver.quit()

Tệp thử nghiệm

import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class TestLoginFlow:
    SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
    LOGIN_URL = "https://staging.staging.example.com/qa-login"

    def test_login_with_captcha(self, browser, captcha_solver):
        browser.get(self.LOGIN_URL)

        # Fill credentials
        browser.find_element(By.ID, "username").send_keys("testuser")
        browser.find_element(By.ID, "password").send_keys("testpass123")

        # Solve CAPTCHA
        token = captcha_solver.solve_recaptcha(self.SITEKEY, self.LOGIN_URL)
        browser.execute_script(
            f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
        )

        # Submit
        browser.find_element(By.ID, "login-btn").click()
        time.sleep(3)

        # Verify login success
        assert "dashboard" in browser.current_url.lower()

    def test_login_wrong_password(self, browser, captcha_solver):
        browser.get(self.LOGIN_URL)
        browser.find_element(By.ID, "username").send_keys("testuser")
        browser.find_element(By.ID, "password").send_keys("wrongpass")

        token = captcha_solver.solve_recaptcha(self.SITEKEY, self.LOGIN_URL)
        browser.execute_script(
            f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
        )

        browser.find_element(By.ID, "login-btn").click()
        time.sleep(3)

        error = browser.find_element(By.CSS_SELECTOR, ".error-message")
        assert error.is_displayed()

class TestContactForm:
    SITEKEY = "0x4AAAA..."
    FORM_URL = "https://staging.example.com/contact"

    def test_contact_form_submission(self, browser, captcha_solver):
        browser.get(self.FORM_URL)

        browser.find_element(By.ID, "name").send_keys("CI Test")
        browser.find_element(By.ID, "email").send_keys("ci@test.com")
        browser.find_element(By.ID, "message").send_keys("Automated CI test")

        token = captcha_solver.solve_turnstile(self.SITEKEY, self.FORM_URL)
        browser.execute_script(
            f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
        )

        browser.find_element(By.CSS_SELECTOR, "button[type='submit']").click()

        WebDriverWait(browser, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, ".success-message"))
        )

Quy trình làm việc hành động của GitHub

name: E2E Tests with CAPTCHA

on:
  push:
    branches: [main, staging]
  pull_request:
    branches: [main]

jobs:
  e2e-tests:
    runs-on: ubuntu-latest

    steps:

      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install Chrome
        uses: browser-actions/setup-chrome@v1
        with:
          chrome-version: stable

      - name: Install ChromeDriver
        uses: nanasess/setup-chromedriver@v2

      - name: Install dependencies
        run: |
          pip install selenium requests pytest pytest-html

      - name: Run E2E tests
        env:
          CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
        run: |
          pytest tests/e2e/ -v --html=report.html --self-contained-html

      - name: Upload test report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: e2e-report
          path: report.html

Cấu hình CI GitLab

e2e_tests:
  stage: test
  image: python:3.11
  services:

    - selenium/standalone-chrome:latest
  variables:
    SELENIUM_REMOTE_URL: "http://selenium__standalone-chrome:4444/wd/hub"
  script:

    - pip install selenium requests pytest
    - pytest tests/e2e/ -v
  artifacts:
    when: always
    reports:
      junit: report.xml

Đường ống Jenkins

pipeline {
    agent any
    environment {
        CAPTCHAAI_API_KEY = credentials('captchaai-api-key')
    }
    stages {
        stage('Setup') {
            steps {
                sh 'pip install selenium requests pytest'
            }
        }
        stage('E2E Tests') {
            steps {
                sh 'pytest tests/e2e/ -v --junitxml=results.xml'
            }
        }
    }
    post {
        always {
            junit 'results.xml'
        }
    }
}

Quản lý chi phí trong CI

Chỉ giải quyết khi cần thiết

import os

def should_run_captcha_tests():
    """Skip CAPTCHA tests in certain environments."""
    if os.environ.get("SKIP_CAPTCHA_TESTS"):
        return False
    if not os.environ.get("CAPTCHAAI_API_KEY"):
        return False
    return True

# In test
import pytest

@pytest.mark.skipif(
    not should_run_captcha_tests(),
    reason="CAPTCHA tests disabled or API key not set"
)
class TestWithCaptcha:
    def test_login(self, browser, captcha_solver):
        pass

Kiểm tra số dư trước bộ thử nghiệm

@pytest.fixture(scope="session", autouse=True)
def check_captcha_balance(captcha_solver):
    import requests
    resp = requests.get(
        f"{captcha_solver.BASE}/res.php",
        params={"key": captcha_solver.api_key, "action": "getbalance"},
    )
    balance = float(resp.text)
    if balance < 0.50:
        pytest.skip(f"CaptchaAI balance too low: ${balance:.2f}")

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
CAPTCHAAI_API_KEY not set Bí mật chưa được định cấu hình Thêm khóa vào bí mật CI
Chrome gặp sự cố trong CI Thiếu cờ --no-sandbox Thêm cờ Chrome headless
Các bài kiểm tra đạt cục bộ, thất bại trong CI Phiên bản trình duyệt khác Ghim phiên bản Chrome trong CI
CAPTCHA hết thời gian Mạng CI chậm Tăng tham số timeout
Các cuộc thử nghiệm rất tốn kém Quá nhiều giải CAPTCHA mỗi lần chạy Sử dụng SKIP_CAPTCHA_TESTS để xây dựng PR

Câu hỏi thường gặp

Mọi lần chạy CI có nên giải quyết CAPTCHA không?

Không. Chạy thử nghiệm CAPTCHA khi hợp nhất vào chính hoặc theo lịch trình (hàng đêm). Bỏ qua mọi PR để giảm chi phí. Sử dụng cờ SKIP_CAPTCHA_TESTS.

Làm cách nào để lưu trữ khóa API một cách an toàn trong CI?

Sử dụng tính năng quản lý bí mật của nền tảng CI của bạn: Bí mật GitHub, Biến CI GitLab hoặc Thông tin xác thực Jenkins. Không bao giờ mã hóa khóa.

Tôi có thể chạy song song các thử nghiệm CAPTCHA không?

Vâng. Mỗi bài kiểm tra sẽ có giải pháp CAPTCHA riêng và CaptchaAI xử lý các yêu cầu đồng thời. Sử dụng pytest-xdist để thực hiện kiểm tra song song.


Hướng dẫn liên quan


Thêm giải pháp CAPTCHA vào CI của bạn —bắt đầu với CaptchaAI.

Os comentários estão desativados para este artigo.

Postagens relacionadas

Use Cases Gửi biểu mẫu tự động với xử lý CAPTCHA
Hướng dẫn thực hành về Gửi biểu mẫu tự động với quy trình xử lý CAPTCHA, với các tình huống thực tế, lời khuyên về quy trình làm việc và các bước có thể thực hi...

Hướng dẫn thực hành về Gửi biểu mẫu tự động với quy trình xử lý CAPTCHA, với các tình huống thực tế, lời khuyê...

Apr 24, 2026
Use Cases Xử lý CAPTCHA trong kiểm tra quy trình đăng ký
Hướng dẫn thực hành về Xử lý CAPTCHA trong quá trình kiểm tra quy trình đăng ký, với các tình huống thực tế, lời khuyên về quy trình làm việc và các bước có thể...

Hướng dẫn thực hành về Xử lý CAPTCHA trong quá trình kiểm tra quy trình đăng ký, với các tình huống thực tế, l...

May 05, 2026
Use Cases Giải quyết CAPTCHA để kiểm tra điểm cuối API trong biểu mẫu web
Hướng dẫn thực hành về cách quyết định CAPTCHA để kiểm tra API giải thích cuối cùng trong web mẫu, với các kịch bản thực tế, lời khuyên về quy trình làm việc và...

Hướng dẫn thực hành về cách quyết định CAPTCHA để kiểm tra API giải thích cuối cùng trong web mẫu, với các kịc...

May 09, 2026