Skip to content

Conversation

@dai008003-dot
Copy link

@dai008003-dot dai008003-dot commented Dec 31, 2025

User description

Thanks for contributing to the Selenium site and documentation!
A PR well described will help maintainers to review and merge it quickly

Before submitting your PR, please check our contributing guidelines.
Avoid large PRs, and help reviewers by making them as simple and short as possible.

Description

Motivation and Context

Types of changes

  • Change to the site (I have double-checked the Netlify deployment, and my changes look good)
  • Code example added (and I also added the example to all translated languages)
  • Improved translation
  • Added new translation (and I also added a notice to each document missing translation)

Checklist

  • I have read the contributing document.
  • I have used hugo to render the site/docs locally and I am sure it works.

PR Type

Enhancement


Description

  • Replaced basic Selenium example with automated Google Forms submission script

  • Added imports for webdriver management, element selection, and timing utilities

  • Implemented loop to submit 200 form responses with randomized answers

  • Added logic to handle text inputs, radio buttons, checkboxes with keyword matching


Diagram Walkthrough

flowchart LR
  A["Basic Selenium Example"] -->|Replace with| B["Google Forms Automation"]
  B --> C["Text Input Handling"]
  B --> D["Radio Button Selection"]
  B --> E["Checkbox Management"]
  B --> F["Form Submission Loop"]
  C --> G["Random Answer Selection"]
  D --> H["Consent Keyword Matching"]
  E --> H
  F --> I["200 Form Submissions"]
Loading

File Walkthrough

Relevant files
Enhancement
hello_selenium.py
Convert to Google Forms automation with intelligent field handling

examples/python/tests/hello/hello_selenium.py

  • Replaced minimal hello world example with comprehensive Google Forms
    automation script
  • Added imports for webdriver management (Service, ChromeDriverManager),
    element selection (By), and utilities (time, random)
  • Implemented automated form filling loop that submits 200 responses
    with randomized text answers and intelligent radio/checkbox selection
  • Added consent keyword matching logic to prioritize specific responses
    for consent-related form fields
  • Integrated timing delays between form submissions and field
    interactions to simulate human behavior
+74/-2   

@netlify
Copy link

netlify bot commented Dec 31, 2025

👷 Deploy request for selenium-dev pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 8a0c945
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Automated request abuse

Description: The new example automates and loops TOTAL = 200 submissions to an external Google Form
(FORM_URL) with randomized answers, which can be readily repurposed for abusive traffic
generation/spam against third-party endpoints (and may violate acceptable-use policies if
copied as-is).
hello_selenium.py [9-78]

Referred Code
FORM_URL = "https://docs.google.com/forms/d/e/XXXXXXXXXXXX/viewform"
TOTAL = 200

TEXT_ANSWERS = [
    "とても良いと思います",
    "特に問題ありません",
    "参考になりました",
    "満足しています",
    "今後も利用したいです"
]

CONSENT_KEYWORDS = ["同意", "承諾", "はい", "許可"]

# ========================

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

for i in range(TOTAL):
    driver.get(FORM_URL)
    time.sleep(random.uniform(2, 3))



 ... (clipped 49 lines)
Supply-chain binary download

Description: Using webdriver_manager.chrome.ChromeDriverManager().install() downloads and executes a
ChromeDriver binary at runtime from the network, creating a supply-chain risk if the
download source, transport, or version pinning is compromised (arbitrary code execution
via a tampered driver).
hello_selenium.py [3-24]

Referred Code
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
import random

# ========= 設定 =========
FORM_URL = "https://docs.google.com/forms/d/e/XXXXXXXXXXXX/viewform"
TOTAL = 200

TEXT_ANSWERS = [
    "とても良いと思います",
    "特に問題ありません",
    "参考になりました",
    "満足しています",
    "今後も利用したいです"
]

CONSENT_KEYWORDS = ["同意", "承諾", "はい", "許可"]

# ========================



 ... (clipped 1 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing error handling: The new Selenium automation has multiple failure points (driver startup, navigation,
element finding/clicking) without any exception handling or try/finally, so errors can
crash the run and may leave the browser open without actionable context.

Referred Code
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

for i in range(TOTAL):
    driver.get(FORM_URL)
    time.sleep(random.uniform(2, 3))

    # ---------- テキスト(約5問) ----------
    text_inputs = driver.find_elements(By.CSS_SELECTOR, "input[type='text']")
    for inp in text_inputs:
        inp.send_keys(random.choice(TEXT_ANSWERS))
        time.sleep(0.2)

    # ---------- ラジオボタン(約20問) ----------
    radio_groups = driver.find_elements(By.CSS_SELECTOR, "div[role='radiogroup']")
    for group in radio_groups:
        radios = group.find_elements(By.CSS_SELECTOR, "div[role='radio']")
        chosen = False

        # 同意系を優先
        for r in radios:
            label = r.text


 ... (clipped 36 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit logging: The new script performs repeated external form submissions but only prints a progress
message without timestamps, actor context, or success/failure details needed to
reconstruct actions if these are considered critical.

Referred Code
for i in range(TOTAL):
    driver.get(FORM_URL)
    time.sleep(random.uniform(2, 3))

    # ---------- テキスト(約5問) ----------
    text_inputs = driver.find_elements(By.CSS_SELECTOR, "input[type='text']")
    for inp in text_inputs:
        inp.send_keys(random.choice(TEXT_ANSWERS))
        time.sleep(0.2)

    # ---------- ラジオボタン(約20問) ----------
    radio_groups = driver.find_elements(By.CSS_SELECTOR, "div[role='radiogroup']")
    for group in radio_groups:
        radios = group.find_elements(By.CSS_SELECTOR, "div[role='radio']")
        chosen = False

        # 同意系を優先
        for r in radios:
            label = r.text
            if any(k in label for k in CONSENT_KEYWORDS):
                r.click()


 ... (clipped 32 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Abbreviated identifiers: Several new identifiers are abbreviated/generic (e.g., TOTAL, inp, r, btn) which can
reduce clarity in an educational example and may require more descriptive naming.

Referred Code
TOTAL = 200

TEXT_ANSWERS = [
    "とても良いと思います",
    "特に問題ありません",
    "参考になりました",
    "満足しています",
    "今後も利用したいです"
]

CONSENT_KEYWORDS = ["同意", "承諾", "はい", "許可"]

# ========================

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

for i in range(TOTAL):
    driver.get(FORM_URL)
    time.sleep(random.uniform(2, 3))

    # ---------- テキスト(約5問) ----------


 ... (clipped 44 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
External target handling: The script hardcodes an external FORM_URL and automates bulk submissions without any
validation/allowlisting or guardrails, which may be inappropriate depending on project
policies and requires human verification of intended usage and safety constraints.

Referred Code
FORM_URL = "https://docs.google.com/forms/d/e/XXXXXXXXXXXX/viewform"
TOTAL = 200

TEXT_ANSWERS = [
    "とても良いと思います",
    "特に問題ありません",
    "参考になりました",
    "満足しています",
    "今後も利用したいです"
]

CONSENT_KEYWORDS = ["同意", "承諾", "はい", "許可"]

# ========================

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

for i in range(TOTAL):
    driver.get(FORM_URL)
    time.sleep(random.uniform(2, 3))

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label
@qodo-code-review
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Replace simple example with complex script

The PR replaces a basic "hello world" script with a complex one for automating
Google Forms. This change is inappropriate for an introductory example file
meant for new users.

Examples:

examples/python/tests/hello/hello_selenium.py [8-78]
# ========= 設定 =========
FORM_URL = "https://docs.google.com/forms/d/e/XXXXXXXXXXXX/viewform"
TOTAL = 200

TEXT_ANSWERS = [
    "とても良いと思います",
    "特に問題ありません",
    "参考になりました",
    "満足しています",
    "今後も利用したいです"

 ... (clipped 61 lines)

Solution Walkthrough:

Before:

# ... imports for selenium, time, random ...
FORM_URL = "https://docs.google.com/forms/d/e/XXXXXXXXXXXX/viewform"
TOTAL = 200
TEXT_ANSWERS = [...]
CONSENT_KEYWORDS = [...]

driver = webdriver.Chrome(...)

for i in range(TOTAL):
    driver.get(FORM_URL)
    # ... find and fill text inputs randomly ...
    # ... find and select radio buttons with special logic ...
    # ... find and select checkboxes with special logic ...
    # ... find and click submit button ...
    print(f"{i+1}/{TOTAL} 回答完了")

driver.quit()

After:

from selenium import webdriver

# Initialize the driver
driver = webdriver.Chrome()

# Navigate to a simple page
driver.get("http://selenium.dev")

# Quit the driver
driver.quit()
Suggestion importance[1-10]: 10

__

Why: The suggestion correctly identifies a fundamental flaw; the PR replaces a simple "hello world" example with a complex, niche script, defeating the purpose of an introductory file.

High
Possible issue
Replace fixed sleep with explicit waits

Replace the fixed time.sleep() with an explicit WebDriverWait to reliably wait
for page elements to load before interacting with them.

examples/python/tests/hello/hello_selenium.py [26-31]

+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+# ... (inside the file)
+
 for i in range(TOTAL):
     driver.get(FORM_URL)
-    time.sleep(random.uniform(2, 3))
+    # Wait up to 10 seconds for the form to be ready by checking for the submit button
+    WebDriverWait(driver, 10).until(
+        EC.visibility_of_element_located((By.CSS_SELECTOR, "div[role='button']"))
+    )
 
     # ---------- テキスト(約5問) ----------
     text_inputs = driver.find_elements(By.CSS_SELECTOR, "input[type='text']")
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies that using time.sleep() for page loads is unreliable and replaces it with an explicit wait (WebDriverWait), which is a crucial best practice in Selenium for creating robust automation scripts.

Medium
Wait for submission confirmation properly

Replace the time.sleep() after form submission with an explicit WebDriverWait
that waits for the URL to change, ensuring the submission is complete before
proceeding to the next iteration.

examples/python/tests/hello/hello_selenium.py [70-78]

+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+# ... (inside the file)
+
 # ---------- 送信 ----------
 buttons = driver.find_elements(By.CSS_SELECTOR, "div[role='button']")
+submit_button_found = False
 for btn in buttons:
     if "送信" in btn.text:
         btn.click()
+        submit_button_found = True
         break
 
+if submit_button_found:
+    # Wait for the confirmation page by checking that the original form URL is no longer present
+    WebDriverWait(driver, 15).until(EC.url_changes(FORM_URL))
+
 print(f"{i+1}/{TOTAL} 回答完了")
-time.sleep(random.uniform(3, 6))
+time.sleep(random.uniform(1, 2)) # Shorter sleep is fine now
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a race condition after form submission and replaces an unreliable time.sleep() with an explicit wait for a URL change, which is a robust method to confirm submission before starting the next iteration.

Medium
Ensure driver quits on error

Wrap the main automation logic in a try...finally block to ensure driver.quit()
is always called, preventing resource leaks if an error occurs.

examples/python/tests/hello/hello_selenium.py [24-80]

 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
-...
-driver.quit()
+try:
+    for i in range(TOTAL):
+        driver.get(FORM_URL)
+        ...
+finally:
+    driver.quit()

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: This is a critical improvement for resource management, ensuring the webdriver instance is always closed via driver.quit() in a finally block, even if errors occur during the execution of the loop.

Medium
Use a more specific element selector

Refine the CSS selector for checkbox groups from the generic div[role='group']
to the more specific div[role='list'] to ensure only checkbox containers are
selected.

examples/python/tests/hello/hello_selenium.py [56-68]

 # ---------- チェックボックス(約5問) ----------
-checkbox_groups = driver.find_elements(By.CSS_SELECTOR, "div[role='group']")
+# Use a more specific selector for checkbox groups (often a list of options)
+checkbox_groups = driver.find_elements(By.CSS_SELECTOR, "div[role='list']")
 for group in checkbox_groups:
     boxes = group.find_elements(By.CSS_SELECTOR, "div[role='checkbox']")
+    # Proceed only if this group actually contains checkboxes
+    if not boxes:
+        continue
     for box in boxes:
         label = box.text
         if any(k in label for k in CONSENT_KEYWORDS):
             if box.get_attribute("aria-checked") == "false":
                 box.click()
         else:
             if random.random() < 0.4:
                 box.click()
     time.sleep(0.2)
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that the div[role='group'] selector is too generic and proposes a more specific one (div[role='list']), which improves the script's reliability by reducing the chance of selecting incorrect elements.

Medium
Add per-iteration error handling

Add a try...except block within the main loop to handle exceptions on a
per-iteration basis, allowing the script to log errors and continue to the next
submission.

examples/python/tests/hello/hello_selenium.py [26-78]

 for i in range(TOTAL):
-    driver.get(FORM_URL)
-    time.sleep(random.uniform(2, 3))
-    # ... form interactions ...
-    print(f"{i+1}/{TOTAL} 回答完了")
-    time.sleep(random.uniform(3, 6))
+    try:
+        driver.get(FORM_URL)
+        time.sleep(random.uniform(2, 3))
+        # ... form interactions ...
+        print(f"{i+1}/{TOTAL} 回答完了")
+        time.sleep(random.uniform(3, 6))
+    except Exception as e:
+        print(f"Error on iteration {i+1}: {e}")
+        continue

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: This suggestion improves the script's resilience by wrapping each loop iteration in a try...except block, allowing the script to continue processing the remaining items even if one iteration fails.

Medium
  • More
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants