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("=== 测试全部通过 ===")