Üniversite ders kayıt sistemleri, kayıt formlarını, sınıf arama sayfalarını ve program planlayıcılarını korumak için reCAPTCHA v2'yi kullanır. Bu sistemleri test eden QA ekiplerinin, CAPTCHA'ları birden fazla test senaryosunda (kayıt iş akışları, bekleme listesi mantığı, koltuk kullanılabilirliği ve son tarih uygulaması) ele alması gerekir. CAPTCHA çözümünü kayıt testine nasıl entegre edeceğiniz aşağıda açıklanmıştır.
CAPTCHA'ların Kayıt Sistemlerinde Nerede Göründüğü
| Kayıt adımı | CAPTCHA türü | Amaç |
|---|---|---|
| Öğrenci giriş sayfası | reCAPTCHA v2 | Kimlik bilgisi doldurmayı önleyin |
| Kurs arama/browse | reCAPTCHA v2 | Otomatik aramaları sınırlayın |
| /drop kursları ekle | reCAPTCHA v2 | Otomatik kaydı engelle |
| Bekleme listesi kaydı | reCAPTCHA v2 | Otomatik kayıt botlarını engelle |
| Zamanlama planlayıcısı | Cloudflare Turnstile | Etkileşimli araçları koruyun |
| Transkript istekleri | reCAPTCHA v2 | İnsan kullanıcıyı doğrulayın |
CAPTCHA Çözme ile Kayıt Testi
import requests
import time
import re
class RegistrationTester:
def __init__(self, api_key, portal_url):
self.api_key = api_key
self.portal_url = portal_url
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def test_login(self, student_id, password):
"""Test login flow with CAPTCHA handling."""
login_page = self.session.get(f"{self.portal_url}/login")
site_key = self._extract_site_key(login_page.text)
token = self._solve_recaptcha(site_key, f"{self.portal_url}/login")
response = self.session.post(f"{self.portal_url}/login", data={
"studentId": student_id,
"password": password,
"g-recaptcha-response": token
})
return {
"status": response.status_code,
"redirected": response.url != f"{self.portal_url}/login",
"success": "dashboard" in response.url or response.status_code == 200
}
def test_course_search(self, term, department, level=None):
"""Test course search returns correct results."""
params = {"term": term, "dept": department}
if level:
params["level"] = level
response = self.session.get(
f"{self.portal_url}/courses/search", params=params
)
if self._has_captcha(response.text):
site_key = self._extract_site_key(response.text)
token = self._solve_recaptcha(
site_key, f"{self.portal_url}/courses/search"
)
response = self.session.post(
f"{self.portal_url}/courses/search",
data={**params, "g-recaptcha-response": token}
)
courses = self._parse_courses(response.text)
return {
"count": len(courses),
"courses": courses,
"all_match_dept": all(
c["department"] == department for c in courses
)
}
def test_enrollment(self, course_id, section):
"""Test enrolling in a course section."""
enroll_page = self.session.get(
f"{self.portal_url}/enroll/{course_id}/{section}"
)
if self._has_captcha(enroll_page.text):
site_key = self._extract_site_key(enroll_page.text)
token = self._solve_recaptcha(
site_key,
f"{self.portal_url}/enroll/{course_id}/{section}"
)
else:
token = None
form_data = {
"courseId": course_id,
"section": section,
"confirm": "true"
}
if token:
form_data["g-recaptcha-response"] = token
response = self.session.post(
f"{self.portal_url}/enroll/submit",
data=form_data
)
return {
"status": response.status_code,
"enrolled": "success" in response.text.lower(),
"waitlisted": "waitlist" in response.text.lower(),
"error": self._extract_error(response.text)
}
def test_seat_availability(self, course_ids):
"""Test seat availability display for multiple courses."""
results = []
for course_id in course_ids:
response = self.session.get(
f"{self.portal_url}/courses/{course_id}"
)
if self._has_captcha(response.text):
site_key = self._extract_site_key(response.text)
token = self._solve_recaptcha(
site_key, f"{self.portal_url}/courses/{course_id}"
)
response = self.session.post(
f"{self.portal_url}/courses/{course_id}",
data={"g-recaptcha-response": token}
)
availability = self._parse_availability(response.text)
results.append({"course_id": course_id, **availability})
return results
def _has_captcha(self, html):
return "g-recaptcha" in html or "recaptcha" in html.lower()
def _extract_site_key(self, html):
match = re.search(r'data-sitekey="([^"]+)"', html)
if match:
return match.group(1)
raise ValueError("reCAPTCHA site key not found")
def _solve_recaptcha(self, site_key, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("reCAPTCHA solve timed out")
def _parse_courses(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
def text_or_empty(node):
return node.text.strip() if node and node.text else ""
courses = []
for row in soup.select(".course-row, tr.course"):
courses.append({
"id": row.get("data-course-id", ""),
"department": text_or_empty(row.select_one(".dept")),
"number": text_or_empty(row.select_one(".number")),
"title": text_or_empty(row.select_one(".title")),
"seats": text_or_empty(row.select_one(".seats"))
})
return courses
def _parse_availability(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
def text_or_none(node):
return node.text.strip() if node and node.text else None
return {
"total_seats": text_or_none(soup.select_one(".total-seats")),
"enrolled": text_or_none(soup.select_one(".enrolled-count")),
"available": text_or_none(soup.select_one(".available-seats")),
"waitlist": text_or_none(soup.select_one(".waitlist-count"))
}
def _extract_error(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
error = soup.select_one(".error-message, .alert-danger")
return error.text.strip() if error else None
Test Paketi Çalıştırıcısı (JavaScript)
class RegistrationTestSuite {
constructor(apiKey, portalUrl) {
this.apiKey = apiKey;
this.portalUrl = portalUrl;
this.results = [];
}
async runAll(testCredentials) {
const tests = [
() => this.testLogin(testCredentials),
() => this.testCourseSearch('Fall2025', 'CS'),
() => this.testEnrollment('CS101', '001'),
() => this.testDropCourse('CS101', '001'),
() => this.testWaitlistFlow('CS201', '001')
];
for (const test of tests) {
try {
const result = await test();
this.results.push({ ...result, passed: true });
} catch (error) {
this.results.push({ name: test.name, error: error.message, passed: false });
}
}
return this.generateReport();
}
async solveRecaptcha(pageUrl, html) {
const match = html.match(/data-sitekey="([^"]+)"/);
if (!match) return null;
const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
method: 'POST',
body: new URLSearchParams({
key: this.apiKey,
method: 'userrecaptcha',
googlekey: match[1],
pageurl: pageUrl,
json: '1'
})
});
const { request: taskId } = await submitResp.json();
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 3000));
const result = await fetch(
`https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
);
const data = await result.json();
if (data.status === 1) return data.request;
}
throw new Error('reCAPTCHA solve timed out');
}
generateReport() {
const passed = this.results.filter(r => r.passed).length;
const failed = this.results.filter(r => !r.passed).length;
return {
total: this.results.length,
passed,
failed,
passRate: `${((passed / this.results.length) * 100).toFixed(1)}%`,
details: this.results
};
}
}
// Usage
const suite = new RegistrationTestSuite('YOUR_API_KEY', 'https://register.university.edu');
const report = await suite.runAll({ studentId: 'test123', password: 'testpass' });
console.log(`Tests: ${report.passed}/${report.total} passed (${report.passRate})`);
CAPTCHA'ları Tetikleyen Test Senaryoları
| Test senaryosu | CAPTCHA sıklığı | Etki |
|---|---|---|
| Birden fazla hesapla giriş yapın | Yüksek | Her giriş denemesi CAPTCHA'yı tetikler |
| Eşzamanlı kayıt testleri | Yüksek | Bot karşıtı koruma |
| Hızlı kurs aramaları | Orta | Hız sınırlı sorgular |
| Zamanlama oluşturma | Düşük | Tek oturumlu etkileşim |
| Önkoşul doğrulama | Düşük | Kayıt akışının bir parçası |
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Her test girişinde CAPTCHA | Oturumun yeniden kullanımı yok | Bir kez kimlik doğrulaması yapın, testleri oturum içinde çalıştırın |
| CAPTCHA'dan sonra kayıt başarısız oluyor | CSRF jetonunun süresi doldu | CAPTCHA ile yeni CSRF jetonunu çıkarın |
| Test verileri çalıştırmalar arasında sıfırlanır | Portal test kayıtlarını temizliyor | Özel test ortamını kullanın |
| reCAPTCHA site anahtarı bulunamadı | SPA, CAPTCHA'yı dinamik olarak oluşturuyor | İşlenen DOM'a erişmek için tarayıcı otomasyonunu kullanın |
SSS
CAPTCHA'ların olmadığı bir test ortamı kullanmalı mıyım?
İdeal olarak, hazırlama ortamları CAPTCHA'ları devre dışı bırakır. Bu mümkün olmadığında (veya üretim davranışını test ederken), CaptchaAI, reCAPTCHA v2 çözümünü yöneterek testlerin manuel müdahale olmadan çalışmasını sağlar.
CI/CD test işlem hatlarında CAPTCHA'ları nasıl ele alırım?
CaptchaAI'yi test bağımlılığı olarak ekleyin. Bir test CAPTCHA ile karşılaştığında bunu API aracılığıyla çözün ve devam edin. Bu, güvenlik özelliklerini devre dışı bırakmadan uçtan uca testlerin güvenilir olmasını sağlar.
Yük altında kaydı CAPTCHA'larla test edebilir miyim?
Evet. CaptchaAI, yük testi için paralel reCAPTCHA çözümünü yönetir. Simüle edilen her öğrenci oturumu için aynı anda birden fazla çözüm isteği gönderin.
İlgili Makaleler
- Api Kullanarak Recaptcha V2 Geri Arama Sorunu Nasıl Çözülür?
- Recaptcha V2 Turnstilesi Aynı Sahada İşleme
- Recaptcha V2 Geri Arama Mekanizması
Sonraki Adımlar
Test kayıt sistemleri uçtan uca —CaptchaAI API anahtarınızı alınve üniversite portalı CAPTCHA'larını test paketinizde yönetin.