Use Cases

Xử lý CAPTCHA trong kiểm tra quy trình đăng ký

Quy trình đăng ký người dùng thử nghiệm diễn ra từ đầu đến cuối - ngay cả khi CAPTCHA chặn quá trình tự động hóa thử nghiệm của bạn.


Tại sao kiểm tra đăng ký cần giải CAPTCHA

Các biểu mẫu đăng ký hầu như luôn được bảo vệ bằng CAPTCHA để ngăn chặn tài khoản bot. Đội ngũ QA cần:

  • Xác minh quy trình đăng ký hoạt động trong quá trình dàn dựng và sản xuất
  • Kiểm tra các trường hợp khó khăn (email trùng lặp, mật khẩu yếu, thiếu trường)
  • Chạy thử nghiệm hồi quy trên mỗi lần triển khai
  • Xác thực vị trí CAPTCHA không phá vỡ biểu mẫu

Kiến trúc thử nghiệm

┌──────────┐     ┌───────────────┐     ┌────────────┐     ┌────────────┐
│ Test Data │────▶│ Fill Form +   │────▶│ Solve      │────▶│ Verify     │
│ Generator │     │ Edge Cases    │     │ CAPTCHA    │     │ Account    │
└──────────┘     └───────────────┘     └────────────┘     └────────────┘

Thực hiện

Trình tạo dữ liệu thử nghiệm

import random
import string
import time

class TestUser:
    def __init__(self, prefix="test"):
        ts = int(time.time())
        rand = ''.join(random.choices(string.ascii_lowercase, k=4))
        self.first_name = f"{prefix}_{rand}"
        self.last_name = "User"
        self.email = f"{prefix}_{ts}_{rand}@testmail.example.com"
        self.username = f"{prefix}_{ts}_{rand}"
        self.password = f"Test!{ts}{rand.upper()}"

    def as_dict(self):
        return {
            "first_name": self.first_name,
            "last_name": self.last_name,
            "email": self.email,
            "username": self.username,
            "password": self.password,
        }

Người kiểm tra đăng ký

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

class CaptchaSolver:
    BASE = "https://ocr.captchaai.com"

    def __init__(self, api_key):
        self.api_key = api_key

    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,
        })

    def _solve(self, params, initial_wait=10):
        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(resp["request"])
        task_id = resp["request"]
        time.sleep(initial_wait)
        for _ in range(60):
            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(result["request"])
        raise TimeoutError("Timed out")

class RegistrationTester:
    def __init__(self, api_key, base_url):
        self.solver = CaptchaSolver(api_key)
        self.base_url = base_url
        self.driver = webdriver.Chrome()
        self.wait = WebDriverWait(self.driver, 10)
        self.results = []

    def _fill(self, selector, value):
        el = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, selector)))
        el.clear()
        el.send_keys(value)

    def _solve_captcha(self):
        html = self.driver.page_source
        page_url = self.driver.current_url

        # Turnstile
        turnstile = self.driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
        if turnstile:
            sitekey = turnstile[0].get_attribute("data-sitekey")
            token = self.solver.solve_turnstile(sitekey, page_url)
            self.driver.execute_script(
                f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
            )
            return

        # reCAPTCHA
        recaptcha = self.driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
        if recaptcha and "recaptcha" in html.lower():
            sitekey = recaptcha[0].get_attribute("data-sitekey")
            token = self.solver.solve_recaptcha(sitekey, page_url)
            self.driver.execute_script(
                f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
            )

    def _get_errors(self):
        """Collect any visible error messages on the page."""
        error_selectors = [
            ".error", ".alert-danger", ".form-error",
            "[role='alert']", ".validation-error",
        ]
        errors = []
        for sel in error_selectors:
            for el in self.driver.find_elements(By.CSS_SELECTOR, sel):
                text = el.text.strip()
                if text:
                    errors.append(text)
        return errors

    def _check_success(self):
        """Check if registration succeeded."""
        html = self.driver.page_source.lower()
        url = self.driver.current_url.lower()
        success_indicators = [
            "welcome", "account created", "verify your email",
            "registration successful", "thank you for registering",
        ]
        return any(ind in html or ind in url for ind in success_indicators)

    # --- Test Cases ---

    def test_valid_registration(self):
        """Test: Valid registration should succeed."""
        user = TestUser()
        self.driver.get(f"{self.base_url}/register")

        self._fill("[name='firstName'], #first-name", user.first_name)
        self._fill("[name='lastName'], #last-name", user.last_name)
        self._fill("[name='email'], #email", user.email)
        self._fill("[name='username'], #username", user.username)
        self._fill("[name='password'], #password", user.password)

        confirm_fields = self.driver.find_elements(By.CSS_SELECTOR, "[name='confirmPassword'], #confirm-password")
        if confirm_fields:
            confirm_fields[0].clear()
            confirm_fields[0].send_keys(user.password)

        self._solve_captcha()

        self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
        time.sleep(3)

        success = self._check_success()
        self.results.append({
            "test": "valid_registration",
            "passed": success,
            "user": user.email,
            "errors": self._get_errors() if not success else [],
        })
        return success

    def test_duplicate_email(self):
        """Test: Duplicate email should show error."""
        user = TestUser()

        # First registration
        self.driver.get(f"{self.base_url}/register")
        self._fill("[name='email'], #email", user.email)
        self._fill("[name='password'], #password", user.password)
        self._fill("[name='firstName'], #first-name", user.first_name)
        self._solve_captcha()
        self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
        time.sleep(3)

        # Second registration with same email
        self.driver.get(f"{self.base_url}/register")
        self._fill("[name='email'], #email", user.email)
        self._fill("[name='password'], #password", user.password)
        self._fill("[name='firstName'], #first-name", "Duplicate")
        self._solve_captcha()
        self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
        time.sleep(3)

        errors = self._get_errors()
        has_error = len(errors) > 0 or not self._check_success()
        self.results.append({
            "test": "duplicate_email",
            "passed": has_error,
            "errors": errors,
        })
        return has_error

    def test_weak_password(self):
        """Test: Weak password should be rejected."""
        user = TestUser()
        self.driver.get(f"{self.base_url}/register")

        self._fill("[name='email'], #email", user.email)
        self._fill("[name='password'], #password", "123")  # Weak password
        self._fill("[name='firstName'], #first-name", user.first_name)
        self._solve_captcha()
        self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
        time.sleep(3)

        errors = self._get_errors()
        rejected = len(errors) > 0 or not self._check_success()
        self.results.append({
            "test": "weak_password",
            "passed": rejected,
            "errors": errors,
        })
        return rejected

    def run_all(self):
        """Run all registration tests."""
        tests = [
            self.test_valid_registration,
            self.test_duplicate_email,
            self.test_weak_password,
        ]
        for test_fn in tests:
            try:
                test_fn()
            except Exception as e:
                self.results.append({
                    "test": test_fn.__name__,
                    "passed": False,
                    "errors": [str(e)],
                })
        return self.results

    def report(self):
        passed = sum(1 for r in self.results if r["passed"])
        total = len(self.results)
        lines = [f"Registration Tests: {passed}/{total} passed", "-" * 40]
        for r in self.results:
            status = "PASS" if r["passed"] else "FAIL"
            lines.append(f"  [{status}] {r['test']}")
            if r.get("errors"):
                for err in r["errors"]:
                    lines.append(f"         {err}")
        return "\n".join(lines)

    def close(self):
        self.driver.quit()

Cách sử dụng

tester = RegistrationTester("YOUR_API_KEY", "https://staging.example.com")

try:
    tester.run_all()
    print(tester.report())
finally:
    tester.close()

Đầu ra:

Registration Tests: 3/3 passed
----------------------------------------
  [PASS] valid_registration
  [PASS] duplicate_email
  [PASS] weak_password

Tích hợp với pytest

import pytest

@pytest.fixture(scope="module")
def tester():
    t = RegistrationTester("YOUR_API_KEY", "https://staging.example.com")
    yield t
    t.close()

def test_valid_registration(tester):
    assert tester.test_valid_registration(), "Valid registration should succeed"

def test_duplicate_email_rejected(tester):
    assert tester.test_duplicate_email(), "Duplicate email should be rejected"

def test_weak_password_rejected(tester):
    assert tester.test_weak_password(), "Weak password should be rejected"

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Đăng ký thành công nhưng kiểm tra báo thất bại Chỉ báo thành công không khớp Thêm văn bản thành công của trang web của bạn vào _check_success()
CAPTCHA không được phát hiện Tải CAPTCHA sau khi bị trì hoãn Thêm time.sleep(2) trước _solve_captcha()
Không tìm thấy trường Cấu trúc HTML khác nhau Cập nhật bộ chọn CSS cho trang web của bạn
Mã thông báo đã hết hạn Giải quyết quá sớm Di chuyển _solve_captcha() đến gần hơn để gửi

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

Làm cách nào để kiểm tra việc đăng ký trên các trang web mà tôi không sở hữu?

Hướng dẫn này là để thử nghiệm các ứng dụng của riêng bạn. Chỉ tự động đăng ký trên các trang web bạn có quyền kiểm tra.

Tôi có thể chạy các thử nghiệm này trong CI/CD không?

Vâng. Sử dụng Chrome headless (options.add_argument("--headless")) và đặt khóa API làm biến môi trường CI.

Làm cách nào để xóa tài khoản thử nghiệm?

Thêm bước phân tích để xóa tài khoản thử nghiệm thông qua API quản trị viên của bạn hoặc sử dụng quy ước đặt tên (test_*) để dễ dàng nhận dạng và dọn dẹp hàng loạt.


Hướng dẫn liên quan


Kiểm tra luồng đăng ký mà không có trình chặn CAPTCHA —sử dụng 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 thử nghiệm tích hợp liên tục
Hướng dẫn thực hành Xử lý CAPTCHA trong thử nghiệm tích hợp liên tục, 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ện...

Hướng dẫn thực hành Xử lý CAPTCHA trong thử nghiệm tích hợp liên tục, với các tình huống thực tế, lời khuyên v...

May 04, 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