audoWin/tests/engine.py

91 lines
2.8 KiB
Python
Raw Permalink Normal View History

2025-12-31 13:51:54 +08:00
import yaml
import time
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 DSLEngine:
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(self.driver, 10)
def _parse_locator(self, locator_str):
"""
解析定位符字符串例如 "id:username" -> (By.ID, "username")
"""
if not locator_str:
return None
by_map = {
"id": By.ID,
"xpath": By.XPATH,
"css": By.CSS_SELECTOR,
"name": By.NAME,
"class": By.CLASS_NAME,
"tag": By.TAG_NAME
}
try:
method, value = locator_str.split(":", 1)
return by_map.get(method.lower()), value
except ValueError:
raise Exception(f"定位符格式错误: {locator_str},应为 '类型:值'")
def execute_step(self, step):
"""
执行单个 DSL 步骤
"""
action = step.get('action')
locator_str = step.get('locator')
value = step.get('value')
desc = step.get('desc', '无描述')
print(f"正在执行: [{action}] - {desc}")
# 解析定位符 (如果有)
locator = self._parse_locator(locator_str)
# === 动作分发 (Action Dispatch) ===
if action == "open":
self.driver.get(value)
elif action == "input":
el = self.wait.until(EC.visibility_of_element_located(locator))
el.clear()
el.send_keys(str(value))
elif action == "click":
el = self.wait.until(EC.element_to_be_clickable(locator))
el.click()
elif action == "wait":
time.sleep(float(value))
elif action == "assert_text":
el = self.wait.until(EC.visibility_of_element_located(locator))
actual_text = el.text
assert value in actual_text, f"断言失败: 期望 '{value}' 包含在 '{actual_text}'"
print(f" -> 断言通过: 发现 '{actual_text}'")
else:
raise Exception(f"未知的动作指令: {action}")
def run_yaml(self, yaml_path):
"""
加载并运行 YAML 文件
"""
with open(yaml_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
print(f"=== 开始测试: {data.get('name')} ===")
for step in data.get('steps', []):
try:
self.execute_step(step)
except Exception as e:
print(f" [X] 步骤执行失败: {e}")
raise e # 抛出异常以终止测试
print("=== 测试全部通过 ===")