你有没有算过:写一个完整的Selenium登录测试脚本,从定位元素到加断言,要花多长时间?30分钟?1小时?
再算算Appium——光配desired_caps、处理混合App的context切换、调试XPath定位,半天就过去了。
如果有个工具,你用一句话描述测试意图,它就能生成可运行的POM框架代码——你会不会心动?
这篇文章带你用Cursor + Selenium/Appium搭建一套AI驱动的自动化测试工作流。不是概念灌水,是可复制的实操流程,每段代码都能跑。
一、为什么是 Cursor?AI 时代测试工程师的新生产力工具
1.1 Cursor是什么
Cursor是一款基于VS Code深度定制的AI原生IDE,内置Claude 3.5 Sonnet和GPT-4o等模型。它不是在编辑器里加了个聊天窗口,而是从底层重新设计了AI与代码的交互方式
对测试工程师来说,这意味着什么?你不需要从零手写每一行定位代码、每一个等待逻辑、每一条断言——你用自然语言描述测试意图,Cursor帮你生成可运行的代码
1.2 三大核心能力
|
|
|
|
|---|---|---|
| Tab 补全 |
|
|
| Composer |
|
|
| Agent 模式 |
|
|
1.3 与Copilot/Claude的区别
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
💡 一句话总结:Copilot是”你写代码它补全”,Cursor是”你说意图它生成”。对于测试脚本的批量生成,Cursor的Composer模式是当前效率天花板
1.4 它不替代什么
说清楚边界Cursor不替代:
- 测试用例设计
——等价类、边界值、正交法,这是你的大脑工作,AI不知道业务风险 - 元素定位策略决策
——用id还是xpath?AI给你建议,但稳定性判断靠你 - 业务逻辑断言
——AI能写assert,但断什么、断多深,取决于你对需求的理解
Cursor是放大器,放大你的测试设计能力,不是替代你的思考
二、环境准备:5分钟搭好工作流
2.1 Cursor安装与配置
-
访问 cursor.com 下载安装(支持Windows/macOS/Linux) -
打开Cursor → Settings → Models → 选择Claude 3.5 Sonnet(代码生成质量好) -
Settings → General → 开启”Auto Save”(Composer生成代码后自动保存)
2.2 Selenium环境(Python)
# 创建虚拟环境python -m venv venvsource venv/bin/activate # Windows: venv\Scripts\activate# 安装依赖pip install selenium pytest webdriver-manager pytest-html# 验证python -c "from selenium import webdriver; print('Selenium OK')"pytest --version
2.3 Appium环境
Appium环境比Selenium复杂,分Android和iOS两部分:
Android必需
-
JDK 8+( java -version验证) -
Android SDK(含adb, adb devices验证) -
Appium Server 2.0+( appium -v验证) -
Appium Driver: appium driver install uiautomator2 -
模拟器或真机(Android Studio自带模拟器即可)
iOS必需(macOS)
-
Xcode 15+(App Store安装,含xcodebuild) -
Appium Driver: appium driver install xcuitest -
ios-deploy( npm install -g ios-deploy) -
libimobiledevice( brew install libimobiledevice) -
模拟器: xcrun simctl list devices available查看可用设备# 安装Appium Python客户端pip install Appium-Python-Client# 验证Android环境adb devicesappium -vappium driver list# 验证iOS环境(仅macOS)xcodebuild -versionxcrun simctl list devices available | grep iPhone -
-
-
-
-
-
-
-
-
三、Cursor + Selenium:Web自动化脚本生成实战
3.1 场景:电商网站登录+搜索+加购物车
我们用一个真实场景演示:测试某电商网站的”用户登录→搜索商品→加入购物车”流程
3.2 传统做法 vs Cursor做法
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 合计 | ~100分钟 | ~7分钟 |
💡 效率提升约14倍。但注意:生成后必须人工Review,重点检查定位策略的稳定性和断言的完整性
3.3 用Composer一步生成POM框架
在Cursor中按Cmd/Ctrl+I打开Composer,输入以下Prompt:
👤 Prompt示例
|
在当前项目下生成一个Selenium Web自动化测试框架,使用Python + pytest,POM设计模式。需求: 1. BasePage类:封装find_element、click、input、wait_for_element、take_screenshot公共方法,统一用WebDriverWait显式等待 2. Pages目录:LoginPage(登录页)、SearchPage(搜索页)、CartPage(购物车页) 3. Tests目录:test_login_search_cart.py,测试流程:登录→搜索”手机”→点击第一个商品→加入购物车→验证购物车数量 4. 定位策略优先级:id > name > css > xpath 5. 每个Page类包含__init__接收driver 6. conftest.py提供driver fixture,用webdriver-manager自动管理ChromeDriver 7. 生成pytest.ini配置文件 |
Cursor会自动创建完整的项目结构:
project/├── pages/│ ├── __init__.py│ ├── base_page.py # BasePage公共方法│ ├── login_page.py # 登录页Page Object│ ├── search_page.py # 搜索页Page Object│ └── cart_page.py # 购物车页Page Object├── tests/│ ├── __init__.py│ ├── conftest.py # pytest fixtures│ └── test_login_search_cart.py # 测试用例├── utils/│ └── __init__.py├── pytest.ini└── requirements.txt
3.4 生成的代码示例:BasePage
from selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Byimport osclass BasePage:"""所有Page Object的基类,封装公共操作"""def __init__(self, driver):self.driver = driverself.wait = WebDriverWait(driver, 10)def find_element(self, *locator):return self.wait.until(EC.presence_of_element_located(locator))def find_clickable(self, *locator):return self.wait.until(EC.element_to_be_clickable(locator))def click(self, *locator):self.find_clickable(*locator).click()def input_text(self, text, *locator):element = self.find_element(*locator)element.clear()element.send_keys(text)def get_text(self, *locator):return self.find_element(*locator).textdef take_screenshot(self, name="screenshot"):path = os.path.join("screenshots", f"{name}.png")os.makedirs("screenshots", exist_ok=True)self.driver.save_screenshot(path)
3.5 生成的代码示例:LoginPage
from selenium.webdriver.common.by import Byfrom pages.base_page import BasePageclass LoginPage(BasePage):"""登录页Page Object"""# 定位策略:id优先,css其次,xpath兜底USERNAME_INPUT = (By.ID, "username")PASSWORD_INPUT = (By.ID, "password")LOGIN_BUTTON = (By.CSS_SELECTOR, "button[type='submit']")ERROR_MESSAGE = (By.CLASS_NAME, "error-msg")def login(self, username, password):"""执行登录操作"""self.input_text(username, *self.USERNAME_INPUT)self.input_text(password, *self.PASSWORD_INPUT)self.click(*self.LOGIN_BUTTON)def get_error_message(self):"""获取错误提示信息"""return self.get_text(*self.ERROR_MESSAGE)def is_loaded(self):"""验证页面是否加载完成"""return self.find_element(*self.USERNAME_INPUT).is_displayed()
3.6 生成的代码示例:测试用例
import pytestfrom pages.login_page import LoginPagefrom pages.search_page import SearchPagefrom pages.cart_page import CartPagedef test_login_search_add_cart(driver):"""测试流程:登录→搜索手机→加购物车→验证"""# Step 1: 登录login_page = LoginPage(driver)login_page.login("testuser", "testpass123")assert login_page.is_loaded() is False # 登录成功应跳转# Step 2: 搜索search_page = SearchPage(driver)search_page.search("手机")assert search_page.get_result_count() > 0# Step 3: 加购物车search_page.click_first_product()cart_page = CartPage(driver)cart_page.add_to_cart()cart_count = cart_page.get_cart_count()assert cart_count >= 1, f"购物车数量异常: {cart_count}"
图片引自微信公众号,扫码关注阅读原文Cursor Composer一键生成POM框架过程线稿
3.7 关键Prompt技巧
生成代码的质量,取决于你描述的精度。三个原则:
- 说清框架
:POM分层 / 线性脚本 / 关键字驱动——不说清楚,AI会给你线性脚本 - 说清定位策略
:id优先 > css其次 > xpath兜底——否则AI可能全用XPath,不稳定 - 说清等待策略
:显式等待WebDriverWait + 10秒——不要求的话,AI可能用time.sleep()
|
🎯 核心原则:Prompt越具体,生成代码越可用。模糊的”写个登录测试”只会给你线性脚本+time.sleep,精确的描述才能生成工程级代码。 |
四、Cursor + Appium:移动端自动化脚本生成实战(Android + iOS)
Appium的复杂度比Selenium高一个量级:平台差异(Android vs iOS)、混合App的context切换、原生组件定位策略不同、手势操作复杂。但Cursor同样能大幅提效
4.1 场景:测试某App的启动→登录→浏览→退出流程
我们分Android和iOS两个平台演示
4.2 Android端:生成Appium测试脚本
👤 Prompt示例(Android)
|
生成一个Appium Android测试脚本,Python + pytest,测试流程:启动App→登录→浏览首页→退出登录。 要求: 1. 登录:用Accessibility ID定位用户名/密码输入框,输入后点击登录按钮 2. 浏览:滑动首页3次,点击第2个商品进入详情页 3. 退出:返回首页→打开侧边栏→点击退出登录→确认退出 4. 每步加WebDriverWait显式等待,超时10秒 5. 滑动用TouchAction的press+move_to+release实现 6. 用pytest标记@pytest.mark.android |
Cursor生成的核心代码:
import pytestfrom appium import webdriverfrom appium.webdriver.common.appiumby import AppiumByfrom appium.webdriver.common.touch_action import TouchActionfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECclass TestAndroidLoginBrowse:@pytest.fixture(scope="class")def driver(self):desired_caps = {"platformName": "Android","automationName": "UiAutomator2","appPackage": "com.example.app", # 替换为实际包名"appActivity": ".MainActivity", # 替换为实际Activity"noReset": True,"newCommandTimeout": 300,}driver = webdriver.Remote("http://127.0.0.1:4723", desired_caps)yield driverdriver.quit()def test_login_browse_logout(self, driver):wait = WebDriverWait(driver, 10)# Step 1: 登录username = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "username_input")))username.send_keys("testuser")password = driver.find_element(AppiumBy.ACCESSIBILITY, "password_input")password.send_keys("testpass123")driver.find_element(AppiumBy.ACCESSIBILITY, "login_button").click()# Step 2: 验证登录成功(首页元素出现)home_tab = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "home_tab")))assert home_tab.is_displayed(), "登录后未进入首页"# Step 3: 滑动浏览首页3次action = TouchAction(driver)size = driver.get_window_size()for i in range(3):action.press(x=size["width"]//2, y=size["height"]//4) \.move_to(x=size["width"]//2, y=size["height"]*3//4) \.release().perform()# Step 4: 点击第2个商品product = wait.until(EC.presence_of_element_located((AppiumBy.XPATH, "(//android.widget.ImageView)[2]")))product.click()# Step 5: 返回首页→打开侧边栏→退出登录driver.back()driver.find_element(AppiumBy.ACCESSIBILITY, "menu_button").click()logout_btn = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "logout_button")))logout_btn.click()# 确认退出confirm = wait.until(EC.presence_of_element_located((AppiumBy.ID, "android:id/button1")))confirm.click()# 验证回到登录页login_screen = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "username_input")))assert login_screen.is_displayed(), "退出后未回到登录页"
4.3 iOS端:生成Appium测试脚本
iOS与Android的脚本结构相似,但有几个关键差异需要注意。在Cursor中生成iOS脚本时,要在Prompt中明确指出:
👤 Prompt示例(iOS)
|
生成一个Appium iOS测试脚本,Python + pytest,测试流程同Android版(启动→登录→浏览→退出) 1. 定位策略优先用Accessibility ID(iOS的accessibility identifier对应XCUIElement的label) 2. iOS的alert弹窗用driver.switch_to.alert处理,不用ACCESSIBILITY定位 3. 滑动用ActionChains(iOS的TouchAction用法与Android不同) 4. App路径用.app文件(模拟器) 5. 用pytest标记@pytest.mark.ios 6. 增加context切换处理(如果是混合App,需切换到WEBVIEW) |
Cursor生成的iOS核心代码:
class TestIOSLoginBrowse:@pytest.fixture(scope="class")def driver(self):desired_caps = {"platformName": "iOS","automationName": "XCUITest","platformVersion": "17.0","deviceName": "iPhone 15","app": "/path/to/MyApp.app", # 替换为实际app路径"noReset": True,"newCommandTimeout": 300,}driver = webdriver.Remote("http://127.0.0.1:4723", desired_caps)yield driverdriver.quit()def test_login_browse_logout(self, driver):wait = WebDriverWait(driver, 10)# Step 1: 登录username = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "username_input")))username.send_keys("testuser")password = driver.find_element(AppiumBy.ACCESSIBILITY, "password_input")password.send_keys("testpass123")driver.find_element(AppiumBy.ACCESSIBILITY, "login_button").click()# Step 2: 处理可能的iOS原生alert弹窗try:alert = driver.switch_to.alertalert.accept()except:pass # 无弹窗则继续# Step 3: 验证登录成功home_tab = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "home_tab")))assert home_tab.is_displayed()# Step 4: iOS滑动(用ActionChains)from selenium.webdriver.common.action_chains import ActionChainssize = driver.get_window_size()for i in range(3):ActionChains(driver) \.move_by_offset(size["width"]//2, size["height"]//4) \.click_and_hold() \.move_by_offset(0, size["height"]//2) \.release() \.perform()ActionChains(driver).reset_actions()# Step 5: 点击第2个商品product = wait.until(EC.presence_of_element_located((AppiumBy.XPATH, "(//XCUIElementTypeImage)[2]")))product.click()# Step 6: 混合App context切换(如果需要)if "WEBVIEW" in driver.contexts:driver.switch_to.context("WEBVIEW")# 在WebView中操作...driver.switch_to.context("NATIVE_APP") # 切回原生# Step 7: 退出登录driver.find_element(AppiumBy.ACCESSIBILITY, "menu_button").click()logout_btn = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "logout_button")))logout_btn.click()confirm = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "确认退出")))confirm.click()# 验证回到登录页login_screen = wait.until(EC.presence_of_element_located((AppiumBy.ACCESSIBILITY, "username_input")))assert login_screen.is_displayed(), "退出后未回到登录页"
4.4 Android vs iOS关键差异对照
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
💡 Cursor使用技巧:生成跨平台脚本时,在Prompt中明确列出Android和iOS的差异点。Cursor会分别生成两套代码,而不是混在一起。如果你只说”写个Appium测试”,它默认生成Android版——iOS的差异容易遗漏
4.5 跨平台测试框架
更高级的玩法:用Cursor生成一套支持双平台的测试基类,通过pytest marker切换平台:
👤 Prompt示例(跨平台)
|
生成一个跨平台Appium测试基类CrossPlatformBasePage,支持Android和iOS双平台 1. 通过pytest marker切换platform,desired_caps在conftest.py中根据marker动态生成 2. 封装公共操作(click, input, swipe, wait)的平台适配层 3. 滑动方法:Android用TouchAction,iOS用ActionChains 4. 提供platform变量,Page Object中可用条件判断处理平台差异 5. 生成conftest.py的driver fixture,根据–platform参数选择Android或iOS的desired_caps |
图片引自微信公众号,扫码关注阅读原文Cursor + Appium跨平台工作流线稿:一套Prompt生成双平台脚本
五、Cursor Rules 配置:打造专属测试脚手架
5.1 .cursorrules文件是什么
这是Cursor的项目级AI行为约束文件。放在项目根目录,Cursor在生成代码时会自动遵守其中的规则。相当于给你的AI助手定一份”工作手册”
5.2 推荐的测试领域Rules配置
在项目根目录创建.cursorrules文件:
# 项目:自动化测试框架# 语言:Python 3.10+# 框架:pytest + Selenium/Appium## 代码结构规则- 使用POM(Page Object Model)设计模式- BasePage封装公共操作,所有Page类继承BasePage- 测试用例文件放在tests/目录,Page Object放在pages/目录- 每个Page类只负责一个页面的元素和操作## 定位策略优先级- Web:id > name > css_selector > xpath- Android:accessibility_id > id > xpath- iOS:accessibility_id > predicate_string > xpath- 禁止使用绝对xpath(如/html/body/div[3]/...)## 等待策略- 统一使用WebDriverWait + expected_conditions- 显式等待超时时间:10秒(可通过参数覆盖)- 禁止使用time.sleep()- 页面加载等待用dom_to_be_loaded## 断言规则- 使用pytest原⽣assert,不引入unittest.AssertionError- 每个测试步骤至少一个断言- 断言失败信息包含:期望值、实际值、上下文## 命名规范- Page类:大驼峰+Page后缀,如LoginPage- 测试函数:test_小驼峰+场景描述,如test_login_with_valid_credentials- 定位变量:全大写+下划线,如USERNAME_INPUT
5.3 配置Cursor Skill:一行指令生成用例
Cursor的Skill功能可以让你把重复的Prompt固化为模板。在Cursor中打开Settings → Rules, Skills, Subagents → 新建Skill:
👤 Skill创建Prompt
|
新增规则:根据需求文档,生成功能测试用例,需要覆盖正向、逆向、异常、并发场景。输出为Python pytest测试函数,包含步骤注释和断言。将用例文件放在tests/目录下 |
Cursor会创建一个SKILL.md文件。以后只需要在对话中输入/generate-test-cases + 需求描述,就能自动生成符合你项目规范的测试用例
5.4 Rules维护建议
-
把.cursorrules纳入Git版本管理,团队共享同一套规则 -
Rules内容随项目演进——发现Cursor生成代码有系统性问题,就在Rules里加约束 -
不要写太多规则——10条以内的核心约束比50条细节规则效果好
六、进阶玩法:Cursor Agent 模式跑测试流水线
6.1 Agent模式是什么
Cursor 0.43版本引入了Agent模式。与Composer不同,Agent可以自主执行多步骤任务——不只是生成代码,还能运行测试、读取日志、分析失败、修复脚本
6.2 场景:Agent修复一个元素定位失效的用例
假设你的Selenium测试用例跑红了,报错NoSuchElementException——页面改版,登录按钮的id变了
👤 Agent Prompt
|
运行 tests/test_login_search_cart.py,分析失败的用例。如果失败原因是元素定位失效,检查当前页面的HTML结构,更新定位策略后重新运行验证 Agent会自动执行以下步骤:
|
图片引自微信公众号,扫码关注阅读原文Cursor Agent自动修复失败用例流程线稿
6.3 效率对比
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 合计 | 25-35分钟 | ~2分钟 |
💡 Agent模式目前适合定位失效、等待超时、断言值微调这类问题。复杂的业务逻辑Bug仍需人工分析
七、效率对比与避坑指南
7.1 整体效率数据
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意:以上数据基于”5年测试经验工程师 + Cursor Pro”的实测结果。新手效率提升更大,但Review时间也要相应增加
7.2 三个常见坑
坑1:生成的定位策略不够稳定Cursor生成的代码可能大量使用XPath或CSS选择器,这些定位方式在页面改版时容易失效 解决:在.cursorrules中强制定位优先级(id > accessibility > css > xpath),并在Review时手动替换不稳定的选择器。Cursor生成后,花5分钟检查每个定位策略——这个时间比手写30分钟值 |
坑2:Appium context切换容易遗漏混合App(原生+WebView)在测试中需要频繁切换context。Cursor如果不知道是混合App,生成的代码可能只在NATIVE_APP中操作,导致WebView中的元素找不到 解决:在Prompt中明确说”这是混合App,WebView部分需要switch_to.context(‘WEBVIEW’)”。更好的做法是写进.cursorrules:所有Appium脚本默认处理context切换 |
坑3:过度依赖AI导致用例设计能力退化这是最隐蔽的坑。当你习惯了”说一句话就出代码”,可能跳过测试用例设计——等价类没分、边界值没测、异常路径没覆盖。代码很快,但测试质量在下降 解决:坚持”先设计再生成”——先用等价类/边界值法列出测试点(纸笔或思维导图),再让Cursor根据你的测试点生成代码。AI负责”写”,你负责”想” |
7.3 正确姿势:AI生成骨架 + 人工打磨细节
- AI生成
框架结构、公共方法、基础定位 - 人工Review
定位策略稳定性、断言完整性、等待策略合理性 - 人工补充
业务特有逻辑、异常路径、数据驱动参数化 - AI修复
日常维护中用Agent模式修复定位失效
八、总结与行动清单
一句话定位
Cursor是自动化测试的效率放大器——它把你从重复的”写模板代码”中解放出来,让你有更多时间做真正有价值的测试设计。但记住:它放大的是你的能力,如果你的设计能力为零,放大后还是零
3步上手计划
- 本周
安装Cursor,用Composer生成一个Selenium登录测试脚本,跑通 - 第二周
配置.cursorrules,生成完整POM框架,接入pytest和测试报告 - 第三周
尝试Appium脚本生成(先Android后iOS),体验Agent修复
5条检查清单
-
项目根目录有.cursorrules文件,定位策略和等待策略已约束 -
Cursor生成的每个Page Object,你都Review了定位策略(是否稳定) -
测试用例的断言不只是assert True,包含具体的期望值和实际值 -
Appium脚本中,Android和iOS的差异点(滑动、alert、元素类型)已处理 -
每次页面改版后,用Cursor Agent模式自动修复,而非手动逐个改
💡 AI不会替代测试工程师,但会用AI的测试工程师,会替代不会用的。从今天开始,让Cursor成为你的测试脚手架
