从算法到智能体:我的聚类研究如何塑造我的自动化逻辑
Source: Dev.to

关键洞见
- 研究塑造思考 – 学术原理影响我处理自动化问题的方式。
- 噪声 = 不稳定 – 用于过滤空间噪声的同一思维模型也适用于测试的稳定性。
- 效率至关重要 – 算法思维驱动等待策略和元素选择的优化。
- 模式识别 – “在混沌中寻找秩序”的心态适用于自愈框架。
“只要点这里,输入那个,检查这个。”
如果你以这种方式思考测试自动化,那你只是在搭建一座纸牌屋。
大多数自动化工程师关注动作——点击什么,输入什么,断言什么。把自动化仅仅当作一连串动作会导致脚本脆弱,一旦 UI 改动了一个类名,脚本就会崩溃。
我并不把自动化看作脚本编写。我把它视为数据问题。
为什么?因为在我用 Python 构建自动化框架之前,我和合著者 Hrishav 正在研究空间数据库中的算法效率。那篇 2012 年发表的研究——并没有教会我可以直接复制粘贴到 Selenium 的具体技巧,却从根本上塑造了我对复杂数据问题的思考方式。
基础:TDCT 算法
2012 年,我和 Hrishav 合著了一篇题为《一种基于多边形方法的大规模空间数据密度聚类技术》(TDCT)的研究论文。
我们解决的问题
如何在庞大且混乱的数据集中找到有意义的模式(簇)——而不被噪声淹没?
当时已有的算法如 DBSCAN 还算不错,但它们在以下方面表现不佳:
- 任意形状 – 真实世界的数据并不形成整齐的圆形。
- 计算成本 – 对每个点与所有其他点进行扫描无法扩展。
- 噪声敏感 – 异常值会扭曲簇的边界。
我们的解决方案:三角形密度
我们没有使用 DBSCAN 那样的圆形邻域,而是将数据点映射到三角形多边形中。这使我们能够:
- 以比径向扫描更高的效率计算密度。
- 检测任意非凸形状的簇。
- 在不破坏核心簇的前提下隔离噪声点。
关键洞见
通过改变问题的几何形状(圆 → 三角形),我们降低了计算复杂度,同时提升了簇检测的准确性。这项合作工作为我至今处理复杂数据问题奠定了基础。
桥梁:这对质量工程有什么意义
“Dhiraj,空间聚类和 Selenium 有什么关系?”
不是代码——是思维方式。
| 研究思维方式 | 自动化应用 |
|---|---|
| 噪声掩盖真实模式 | 不稳定的测试掩盖真实缺陷 |
| 暴力扫描无法扩展 | 线性轮询和硬性等待无法扩展 |
| 几何形状决定效率 | 框架的结构决定其韧性 |
| 区分稳定核心与噪声 | 区分可靠的元素属性与动态属性 |
关键在于问题的框定
当我遇到复杂的自动化挑战时,我不会立刻想“我需要哪个 Selenium 命令?”而是先问:
- 这里的数据结构是什么?(DOM 是一棵树;测试结果是时间序列数据。)
- 噪声与信号的界限在哪里?(哪些元素属性是稳定的?哪些失败是真正的 bug?)
- 如何降低复杂度?(我能像 TDCT 那样优化问题的“几何形状”吗?)
这种由多年算法研究训练出的思维模型,影响着我做出的每一个框架决策。
应用思维方式:实用示例
示例 1:带回退逻辑的多属性元素定位
暴力方式(单点故障):
# If ID changes, everything breaks
element = driver.find_element(By.ID, "checkout-btn-v3")
算法式方式(按可靠性对多个属性进行聚类):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
def find_element_with_fallback(driver, strategies: list[tuple]) -> WebElement:
"""
Analyze multiple 'data points' (attributes) ordered by reliability.
Returns the first element that becomes clickable.
"""
for strategy, locator in strategies:
try:
element = WebDriverWait(driver, 2).until(
EC.element_to_be_clickable((strategy, locator))
)
return element
except TimeoutException:
continue
raise NoSuchElementException("All strategies exhausted")
checkout_strategies = [
(By.CSS_SELECTOR, "[data-testid='checkout']"), # Most stable: test IDs
(By.CSS_SELECTOR, "button[aria-label='Checkout']"), # Accessibility attrs
(By.XPATH, "//button[contains(text(), 'Checkout')]"), # Text content
(By.CSS_SELECTOR, ".cart-section button.primary"), # Structural fallback
]
checkout_btn = find_element_with_fallback(driver, checkout_strategies)
第一个策略充当“密度核心”。如果它失效,我们会优雅地回退到仍然有效但稍逊的“邻居”。
示例 2:自愈元素定位
静态方式(脆弱、对噪声敏感):
driver.find_element(By.ID, "submit-btn-v3") # Breaks when ID changes
自适应方式(类似聚类的韧性):
def self_heal_find(driver, primary_locator, fallback_locators):
"""
Try the primary locator; if it fails, evaluate fallback locators
based on attribute stability and similarity to known anchors.
"""
try:
return driver.find_element(*primary_locator)
except NoSuchElementException:
for loc in fallback_locators:
candidates = driver.find_elements(*loc)
if candidates:
# Simple heuristic: pick the element with the most stable attributes
return max(candidates, key=lambda e: evaluate_stability(e))
raise NoSuchElementException("Element could not be healed")
def evaluate_stability(element):
# Placeholder for a real scoring function (e.g., based on data‑testids,
# ARIA labels, relative position to stable anchors, etc.)
score = 0
if element.get_attribute("data-testid"):
score += 3
if element.get_attribute("aria-label"):
score += 2
# Add more heuristics as needed
return score
primary = (By.ID, "submit-btn-v3")
fallbacks = [
(By.CSS_SELECTOR, "[data-testid='submit']"),
(By.XPATH, "//button[contains(text(),'Submit')]"),
(By.CSS_SELECTOR, "button.primary")
]
submit_btn = self_heal_find(driver, primary, fallbacks)
该实现并非 TDCT 的字面复制,但思路相同:评估多个数据点并选取最可靠的组合。
体现此哲学的工具
当我创建 Lumos ShadowDOM 或 Visual Guard 等包时,并没有有意识地实现聚类算法。然而设计决策仍然呼应了相同的原则:
- 高效遍历 Shadow DOM → 在暴力遍历之前先了解结构。
- 使用 SSIM 的视觉回归 → 用数学模型(而非像素逐个比较)找出有意义的差异。
- 框架自愈 → 将元素属性视为具有不同可靠性的“数据点”。
研究并没有给我可直接复制粘贴的解决方案,而是提供了一种视角:把自动化看作数据问题,而非脚本问题。
结论:自动化不只是代码——它是逻辑
无论是多年以前发表的 TDCT 算法,还是我今天构建的 自动化工具和库,目标始终如一:
在混沌中建立秩序。
DOM 本身是混沌的。当以研究驱动的思维方式来对待测试自动化时,能够施加结构、降低不稳定性,并实现优雅的扩展。