01
大家好,我是测试员周周,全网同名。这是 Hermes 系列第 4 篇,也是商品管理模块的测试实战篇。
上一篇我们把登录回归跑通了一条闭环。这篇做天然更“碎”的事:新增 + 查询——字段多、边界多、组合多,最适合验证 Hermes 能不能把表格式思维一次拉齐。
如果你也遇到过这些场景,这篇就是给你写的: - 每次发版都要手动测商品后台,重复劳动 - 新增场景多(必填、选填、价格/库存边界) - 查询要考虑多种条件组合,脑子能想到,手抄用例抄不完 - 测试数据准备烦:录几条假数据就要半下午
我承诺一个结果:你不需要先会写 Page Object,只要会给 URL、账号、字段大致长什么样,Hermes 能帮你把用例表和脚本骨架先顶上——你再做人审与微调。
02
再补一层背景,和第 3 篇「登录」是同一套世界观。
很多团队第一步会想上测试平台:用例库、执行记录、报表——没问题,但前后端 + 权限 + 运营一上来就是小产品量级,离不开持续投入。
另一条路是 Skills / 插件化:轻一些,但你照样要维护「机器可读」的制品,改一版页面可能要改一版技能说明。
Hermes 这条路径里,我更常做的是:把商品管理页直接交给它(链接、截图、关键字段名),让它先读结构、列风险、吐用例草案,再决定是否落 Playwright。配置齐的话,不必先写一堆独立 Skills 文件,对话就能走完大半;要固化了,再抽到团队模板库。
底线不变:内网隔离、合规要求时,生成脚本在你本地跑;财务级精度的断言,仍建议人工点名 P0 文案,而不是全信第一版模型输出。
03
本篇交付:商品管理里的 新增商品 + 查询商品,共 11 条用例思路 + 一份可运行的 Python + Playwright 示例骨架(含 Page Object)。
你会带走: - 比登录多一倍的「组合爆炸」怎么拆成可执行表 - 同一套提示词模板,换模块仍能复用 - 知道数据怎么造、列表断言怎么收敛才不 brittle
04
系统背景
我们要测试的是一个电商秒杀与财务一体化系统的商品管理模块。
系统信息: - 系统 URL:http://localhost:5000 - 登录账号:admin / 123456 - 商品管理页面:http://localhost:5000/products#manage
测试目标
本次实战聚焦商品管理的两个核心功能:
功能 1:新增商品
| 测试项 | 测试内容 | 预期结果 |
|---|---|---|
| 正常新增 | 填写所有必填项(商品名称、价格、库存) | 添加成功,列表显示新商品 |
| 商品名称为空 | 不输入商品名称,其他必填 | 提示"请输入商品名称" |
| 价格为负数 | 价格输入 -100 | 提示"价格必须大于 0" |
| 价格为 0 | 价格输入 0 | 提示"价格必须大于 0" |
| 库存为负数 | 库存输入 -50 | 提示"库存必须大于等于 0" |
| 价格超过最大值 | 价格输入 999999999 | 提示"价格超出范围"或自动格式化 |
功能 2:查询商品
| 测试项 | 测试内容 | 预期结果 |
|---|---|---|
| 按名称查询 | 输入商品名称关键词 | 显示匹配的商品列表 |
| 按价格范围查询 | 输入最低价格和最高价格 | 显示价格范围内的商品 |
| 组合查询 | 名称 + 价格范围同时输入 | 显示同时满足条件的商品 |
| 查询无结果 | 输入不存在的商品名称 | 显示"暂无数据"或空列表 |
| 重置查询 | 点击重置按钮 | 清空搜索条件,显示全部商品 |
测试环境
| 项目 | 配置 |
|---|---|
| 系统 URL | http://localhost:5000 |
| 登录账号 | admin / 123456 |
| 浏览器 | Chrome / Firefox |
| 测试工具 | Hermes Agent + Playwright |
05
登录之后的模块测试,字段越多,越适合先让 Hermes「看页面再写表」;下面仍保留带完整元素 ID 的「明细版」,方便你一键对齐后文长脚本。
更轻的一版起手式(可选)
先把商品管理页丢给 Hermes,让它自己长眼睛,再进入正文里那大段「元素 ID 清单」也可以:
bash📋 复制
请打开(或根据截图分析)电商后台的商品管理页,识别新增商品所需的表单字段、查询区的输入项与按钮。在已知登录账号 admin/123456、系统 http://localhost:5000 的前提下,列出「新增商品」与「查询商品」的 P0/P1 用例草案(表格列:名称、数据、预期),暂不写代码。
它若已能访问页面,通常会顺便给出更稳的定位策略(id / placeholder / role);你再把结论粘贴回「明细版」提示词里,后文示例不易跑偏。
第一步:告诉 Hermes 要做什么
打开你与 Hermes 的对话(飞书机器人或 CLI),输入以下提示词:
bash📋 复制
我要对电商后台管理系统的商品管理模块进行测试。系统信息:- 登录页面:http://localhost:5000/login- 商品管理页面:http://localhost:5000/products#manage- 测试账号:用户名 admin,密码 123456- 新增商品表单元素: - 商品名称输入框 ID:product-name - 价格输入框 ID:product-price - 库存输入框 ID:product-stock - 添加按钮 ID:add-btn - 成功提示元素 class:success-message- 查询功能元素: - 搜索框 ID:search-input - 最低价格 ID:min-price - 最高价格 ID:max-price - 查询按钮 ID:search-btn - 重置按钮 ID:reset-btn - 商品列表表格 ID:product-table请帮我:1. 拆解新增商品和查询商品的测试任务为可执行的步骤2. 生成测试用例表格(新增商品 6 个用例,查询商品 5 个用例)3. 输出结构化的测试用例表格
Hermes 返回的任务拆解
Hermes 会返回类似下面的内容:
bash📋 复制
【任务理解】你需要对电商后台商品管理模块的两个功能进行测试:1. 新增商品功能(6 个测试场景)2. 查询商品功能(5 个测试场景)【测试步骤拆解】步骤 1:登录系统- 打开登录页面- 输入用户名 admin- 输入密码 123456- 点击登录- 验证是否跳转到后台首页步骤 2:进入商品管理页面- 点击商品管理菜单- 验证是否进入 /products#manage 页面步骤 3:执行新增商品测试用例- 用例 1:正常新增商品- 用例 2:商品名称为空- 用例 3:价格为负数- 用例 4:价格为 0- 用例 5:库存为负数- 用例 6:价格超过最大值步骤 4:执行查询商品测试用例- 用例 1:按名称查询- 用例 2:按价格范围查询- 用例 3:组合查询- 用例 4:查询无结果- 用例 5:重置查询步骤 5:记录结果并生成报告- 每个用例的执行结果(通过/失败)- 实际响应与预期对比- 截图保存(失败用例)- 生成结构化测试报告
第二步:让 Hermes 生成测试用例
继续输入:
bash📋 复制
请把上面的测试步骤转换成可执行的测试用例表格,包含以下列:- 用例编号(TC001-TC011)- 功能模块(新增商品/查询商品)- 用例名称- 前置条件- 测试步骤- 测试数据- 预期结果- 优先级(P0/P1)
Hermes 会返回:
bash📋 复制
【商品管理功能测试用例】| 编号 | 功能模块 | 名称 | 前置条件 | 测试步骤 | 测试数据 | 预期结果 | 优先级 ||------|----------|------|----------|----------|----------|----------|--------|| TC001 | 新增商品 | 正常新增商品 | 已登录 | 1.点击添加商品 2.输入商品名称 3.输入价格 4.输入库存 5.点击添加 | 名称:测试商品 001 价格:99.9 库存:100 | 添加成功,列表显示新商品,提示"添加成功" | P0 || TC002 | 新增商品 | 商品名称为空 | 已登录 | 1.点击添加商品 2.不输入名称 3.输入价格 4.输入库存 5.点击添加 | 名称:(空) 价格:99.9 库存:100 | 提示"请输入商品名称",添加失败 | P0 || TC003 | 新增商品 | 价格为负数 | 已登录 | 1.点击添加商品 2.输入名称 3.输入负数价格 4.输入库存 5.点击添加 | 名称:测试商品 002 价格:-100 库存:100 | 提示"价格必须大于 0",添加失败 | P0 || TC004 | 新增商品 | 价格为 0 | 已登录 | 1.点击添加商品 2.输入名称 3.输入价格 0 4.输入库存 5.点击添加 | 名称:测试商品 003 价格:0 库存:100 | 提示"价格必须大于 0",添加失败 | P1 || TC005 | 新增商品 | 库存为负数 | 已登录 | 1.点击添加商品 2.输入名称 3.输入价格 4.输入负数库存 5.点击添加 | 名称:测试商品 004 价格:99.9 库存:-50 | 提示"库存必须大于等于 0",添加失败 | P0 || TC006 | 新增商品 | 价格超过最大值 | 已登录 | 1.点击添加商品 2.输入名称 3.输入超大价格 4.输入库存 5.点击添加 | 名称:测试商品 005 价格:999999999 库存:100 | 提示"价格超出范围"或自动格式化 | P1 || TC007 | 查询商品 | 按名称查询 | 已登录,列表有数据 | 1.在搜索框输入关键词 2.点击查询 | 关键词:测试 | 显示名称包含"测试"的商品 | P0 || TC008 | 查询商品 | 按价格范围查询 | 已登录,列表有数据 | 1.输入最低价格 2.输入最高价格 3.点击查询 | 最低价:50 最高价:150 | 显示价格在 50-150 之间的商品 | P1 || TC009 | 查询商品 | 组合查询 | 已登录,列表有数据 | 1.输入关键词 2.输入价格范围 3.点击查询 | 关键词:测试 最低价:50 最高价:150 | 显示同时满足条件的商品 | P1 || TC010 | 查询商品 | 查询无结果 | 已登录 | 1.输入不存在的商品名称 2.点击查询 | 关键词:不存在的商品 XYZ | 显示"暂无数据"或空列表 | P1 || TC011 | 查询商品 | 重置查询 | 已登录,已输入查询条件 | 1.输入查询条件 2.点击重置 | 任意条件 | 清空所有查询条件,显示全部商品 | P1 |
06
第三步:生成 Playwright 自动化脚本
输入提示词:
bash📋 复制
请用 Python + Playwright 为上面的 11 个测试用例生成自动化测试脚本。要求:1. 包含登录功能(所有测试用例的前置步骤)2. 每个用例一个独立函数3. 包含断言检查4. 失败时自动截图5. 输出测试结果到 JSON 文件6. 添加详细注释,方便新人理解7. 使用 Page Object 模式,便于维护
Hermes 会生成类似下面的脚本:
bash📋 复制
#!/usr/bin/env python3"""电商后台商品管理功能回归测试脚本使用 Playwright 进行浏览器自动化测试测试范围:新增商品 + 查询商品生成:Hermes Agent"""from playwright.sync_api import sync_playwright, expectimport jsonfrom datetime import datetimeimport os# ==================== 配置区域 ====================BASE_URL = "http://localhost:5000"LOGIN_URL = f"{BASE_URL}/login"PRODUCTS_URL = f"{BASE_URL}/products#manage"TEST_ACCOUNT = {"username": "admin", "password": "123456"}# 创建截图目录os.makedirs("screenshots", exist_ok=True)# ==================== Page Object 类 ====================class LoginPage: """登录页面对象""" def __init__(self, page): self.page = page def navigate(self): """打开登录页面""" self.page.goto(LOGIN_URL, timeout=10000) return self def login(self, username, password): """执行登录""" self.page.fill("#username", username) self.page.fill("#password", password) self.page.click("#login-btn") self.page.wait_for_timeout(2000) return self def is_logged_in(self): """验证是否登录成功""" # 检查是否跳转到后台页面 return "/products" in self.page.url or "/dashboard" in self.page.urlclass ProductPage: """商品管理页面对象""" def __init__(self, page): self.page = page def navigate(self): """打开商品管理页面""" self.page.goto(PRODUCTS_URL, timeout=10000) self.page.wait_for_timeout(2000) return self # ----- 新增商品相关方法 ----- def click_add_product(self): """点击添加商品按钮""" self.page.click("#add-btn") self.page.wait_for_timeout(1000) return self def fill_product_name(self, name): """输入商品名称""" if name: self.page.fill("#product-name", name) return self def fill_product_price(self, price): """输入商品价格""" if price is not None: self.page.fill("#product-price", str(price)) return self def fill_product_stock(self, stock): """输入商品库存""" if stock is not None: self.page.fill("#product-stock", str(stock)) return self def submit_add_product(self): """提交添加商品表单""" self.page.click("#add-btn") self.page.wait_for_timeout(2000) return self def get_success_message(self): """获取成功提示信息""" try: return self.page.text_content(".success-message") except: return None def get_error_message(self): """获取错误提示信息""" try: return self.page.text_content(".error-message") or self.page.text_content(".alert") except: return None # ----- 查询商品相关方法 ----- def fill_search_keyword(self, keyword): """输入搜索关键词""" if keyword: self.page.fill("#search-input", keyword) return self def fill_min_price(self, price): """输入最低价格""" if price is not None: self.page.fill("#min-price", str(price)) return self def fill_max_price(self, price): """输入最高价格""" if price is not None: self.page.fill("#max-price", str(price)) return self def click_search(self): """点击查询按钮""" self.page.click("#search-btn") self.page.wait_for_timeout(2000) return self def click_reset(self): """点击重置按钮""" self.page.click("#reset-btn") self.page.wait_for_timeout(1000) return self def get_product_count(self): """获取商品列表数量""" try: rows = self.page.query_selector_all("#product-table tbody tr") return len(rows) except: return 0 def is_empty_result(self): """检查是否为空结果""" try: empty_msg = self.page.text_content(".empty-message") or self.page.text_content(".no-data") return empty_msg is not None or self.get_product_count() == 0 except: return self.get_product_count() == 0# ==================== 测试执行函数 ====================def run_test(case_id, case_name, test_func, expected_success, expected_message=None): """ 执行单个测试用例 参数: case_id: 用例编号 case_name: 用例名称 test_func: 测试函数 expected_success: 是否预期成功 expected_message: 预期的提示信息 返回: dict: 测试结果 """ result = { "case_id": case_id, "case_name": case_name, "status": "pending", "actual_message": "", "screenshot": None, "error": None } with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() try: # 步骤 1:登录 login_page = LoginPage(page) login_page.navigate().login( TEST_ACCOUNT["username"], TEST_ACCOUNT["password"] ) # 验证登录成功 if not login_page.is_logged_in(): result["status"] = "failed" result["actual_message"] = "登录失败" result["screenshot"] = f"screenshots/{case_id}_login_failed.png" page.screenshot(path=result["screenshot"]) return result # 步骤 2:进入商品管理页面 product_page = ProductPage(page) product_page.navigate() # 步骤 3:执行具体测试 test_result = test_func(product_page) # 步骤 4:验证结果 if expected_success: if test_result.get("success", False): result["status"] = "passed" result["actual_message"] = test_result.get("message", "测试通过") else: result["status"] = "failed" result["actual_message"] = test_result.get("message", "测试失败") result["screenshot"] = f"screenshots/{case_id}_failed.png" page.screenshot(path=result["screenshot"]) else: # 预期失败的场景(如验证错误提示) if not test_result.get("success", True): result["status"] = "passed" result["actual_message"] = test_result.get("message", "正确捕获错误") else: result["status"] = "failed" result["actual_message"] = test_result.get("message", "未捕获预期错误") result["screenshot"] = f"screenshots/{case_id}_failed.png" page.screenshot(path=result["screenshot"]) except Exception as e: result["status"] = "failed" result["error"] = str(e) result["screenshot"] = f"screenshots/{case_id}_error.png" page.screenshot(path=result["screenshot"]) finally: browser.close() return result# ==================== 测试用例定义 ====================def test_add_product_normal(product_page): """TC001: 正常新增商品""" product_page.click_add_product() product_page.fill_product_name("测试商品 001") product_page.fill_product_price(99.9) product_page.fill_product_stock(100) product_page.submit_add_product() message = product_page.get_success_message() if message and "成功" in message: return {"success": True, "message": f"添加成功:{message}"} return {"success": False, "message": f"添加失败:{message}"}def test_add_product_empty_name(product_page): """TC002: 商品名称为空""" product_page.click_add_product() product_page.fill_product_name("") # 空名称 product_page.fill_product_price(99.9) product_page.fill_product_stock(100) product_page.submit_add_product() error = product_page.get_error_message() if error and "名称" in error: return {"success": False, "message": f"正确提示:{error}"} return {"success": True, "message": f"未提示错误:{error}"}def test_add_product_negative_price(product_page): """TC003: 价格为负数""" product_page.click_add_product() product_page.fill_product_name("测试商品 002") product_page.fill_product_price(-100) # 负数价格 product_page.fill_product_stock(100) product_page.submit_add_product() error = product_page.get_error_message() if error and "价格" in error: return {"success": False, "message": f"正确提示:{error}"} return {"success": True, "message": f"未提示错误:{error}"}def test_add_product_zero_price(product_page): """TC004: 价格为 0""" product_page.click_add_product() product_page.fill_product_name("测试商品 003") product_page.fill_product_price(0) # 价格为 0 product_page.fill_product_stock(100) product_page.submit_add_product() error = product_page.get_error_message() if error and "价格" in error: return {"success": False, "message": f"正确提示:{error}"} return {"success": True, "message": f"未提示错误:{error}"}def test_add_product_negative_stock(product_page): """TC005: 库存为负数""" product_page.click_add_product() product_page.fill_product_name("测试商品 004") product_page.fill_product_price(99.9) product_page.fill_product_stock(-50) # 负数库存 product_page.submit_add_product() error = product_page.get_error_message() if error and "库存" in error: return {"success": False, "message": f"正确提示:{error}"} return {"success": True, "message": f"未提示错误:{error}"}def test_add_product_large_price(product_page): """TC006: 价格超过最大值""" product_page.click_add_product() product_page.fill_product_name("测试商品 005") product_page.fill_product_price(999999999) # 超大价格 product_page.fill_product_stock(100) product_page.submit_add_product() # 可能成功也可能失败,取决于系统设计 message = product_page.get_success_message() or product_page.get_error_message() return {"success": True, "message": f"处理结果:{message}"}def test_search_by_name(product_page): """TC007: 按名称查询""" product_page.fill_search_keyword("测试") product_page.click_search() count = product_page.get_product_count() if count > 0: return {"success": True, "message": f"查询到 {count} 个商品"} return {"success": False, "message": "未查询到商品"}def test_search_by_price_range(product_page): """TC008: 按价格范围查询""" product_page.fill_min_price(50) product_page.fill_max_price(150) product_page.click_search() count = product_page.get_product_count() return {"success": True, "message": f"查询到 {count} 个商品"}def test_search_combined(product_page): """TC009: 组合查询""" product_page.fill_search_keyword("测试") product_page.fill_min_price(50) product_page.fill_max_price(150) product_page.click_search() count = product_page.get_product_count() return {"success": True, "message": f"查询到 {count} 个商品"}def test_search_no_result(product_page): """TC010: 查询无结果""" product_page.fill_search_keyword("不存在的商品 XYZ") product_page.click_search() if product_page.is_empty_result(): return {"success": True, "message": "正确显示空结果"} return {"success": False, "message": "未显示空结果"}def test_reset_search(product_page): """TC011: 重置查询""" # 先输入一些查询条件 product_page.fill_search_keyword("测试") product_page.fill_min_price(50) product_page.click_search() # 点击重置 product_page.click_reset() # 验证查询条件是否清空(这里简化验证) return {"success": True, "message": "重置完成"}# ==================== 主测试函数 ====================def main(): """主测试函数""" print("=" * 60) print("电商后台商品管理功能回归测试") print("=" * 60) # 定义所有测试用例 test_cases = [ {"case_id": "TC001", "case_name": "正常新增商品", "test_func": test_add_product_normal, "expected_success": True}, {"case_id": "TC002", "case_name": "商品名称为空", "test_func": test_add_product_empty_name, "expected_success": False}, {"case_id": "TC003", "case_name": "价格为负数", "test_func": test_add_product_negative_price, "expected_success": False}, {"case_id": "TC004", "case_name": "价格为 0", "test_func": test_add_product_zero_price, "expected_success": False}, {"case_id": "TC005", "case_name": "库存为负数", "test_func": test_add_product_negative_stock, "expected_success": False}, {"case_id": "TC006", "case_name": "价格超过最大值", "test_func": test_add_product_large_price, "expected_success": True}, {"case_id": "TC007", "case_name": "按名称查询", "test_func": test_search_by_name, "expected_success": True}, {"case_id": "TC008", "case_name": "按价格范围查询", "test_func": test_search_by_price_range, "expected_success": True}, {"case_id": "TC009", "case_name": "组合查询", "test_func": test_search_combined, "expected_success": True}, {"case_id": "TC010", "case_name": "查询无结果", "test_func": test_search_no_result, "expected_success": True}, {"case_id": "TC011", "case_name": "重置查询", "test_func": test_reset_search, "expected_success": True}, ] # 执行测试 results = [] for case in test_cases: print(f"\n执行 {case['case_id']}: {case['case_name']}...") result = run_test( case["case_id"], case["case_name"], case["test_func"], case["expected_success"] ) results.append(result) # 打印结果 status_icon = "✅" if result["status"] == "passed" else "❌" print(f"{status_icon} {case['case_id']}: {result['status']}") print(f" 结果:{result['actual_message']}") # 生成测试报告 report = { "test_time": datetime.now().isoformat(), "module": "商品管理", "total_cases": len(results), "passed": sum(1 for r in results if r["status"] == "passed"), "failed": sum(1 for r in results if r["status"] == "failed"), "results": results } # 保存报告 with open("product_test_report.json", "w", encoding="utf-8") as f: json.dump(report, f, ensure_ascii=False, indent=2) # 打印汇总 print("\n" + "=" * 60) print("测试汇总") print("=" * 60) print(f"总用例数:{report['total_cases']}") print(f"通过:{report['passed']} ✅") print(f"失败:{report['failed']} ❌") pass_rate = report['passed'] / report['total_cases'] * 100 if report['total_cases'] > 0 else 0 print(f"通过率:{pass_rate:.1f}%") print(f"\n详细报告已保存到:product_test_report.json")if __name__ == "__main__": main()
07
第四步:运行测试脚本
在终端执行以下命令:
bash📋 复制
# 1. 安装依赖(首次执行需要)pip install playwright# 2. 安装浏览器playwright install chromium# 3. 创建截图目录mkdir -p screenshots# 4. 运行测试python product_test.py
执行过程
你会看到类似这样的输出:
bash📋 复制
============================================================电商后台商品管理功能回归测试============================================================执行 TC001: 正常新增商品...✅ TC001: passed 结果:添加成功:商品添加成功执行 TC002: 商品名称为空...✅ TC002: passed 结果:正确提示:请输入商品名称执行 TC003: 价格为负数...✅ TC003: passed 结果:正确提示:价格必须大于 0执行 TC004: 价格为 0...✅ TC004: passed 结果:正确提示:价格必须大于 0执行 TC005: 库存为负数...✅ TC005: passed 结果:正确提示:库存必须大于等于 0执行 TC006: 价格超过最大值...✅ TC006: passed 结果:处理结果:价格超出范围执行 TC007: 按名称查询...✅ TC007: passed 结果:查询到 5 个商品执行 TC008: 按价格范围查询...✅ TC008: passed 结果:查询到 3 个商品执行 TC009: 组合查询...✅ TC009: passed 结果:查询到 2 个商品执行 TC010: 查询无结果...✅ TC010: passed 结果:正确显示空结果执行 TC011: 重置查询...✅ TC011: passed 结果:重置完成============================================================测试汇总============================================================总用例数:11通过:11 ✅失败:0 ❌通过率:100.0%详细报告已保存到:product_test_report.json
08
JSON 报告内容
打开 product_test_report.json,你会看到:
bash📋 复制
{ "test_time": "2026-04-08T19:30:00", "module": "商品管理", "total_cases": 11, "passed": 11, "failed": 0, "results": [ { "case_id": "TC001", "case_name": "正常新增商品", "status": "passed", "actual_message": "添加成功:商品添加成功", "screenshot": null, "error": null }, { "case_id": "TC002", "case_name": "商品名称为空", "status": "passed", "actual_message": "正确提示:请输入商品名称", "screenshot": null, "error": null } // ... 其他用例 ]}
HTML 可视化报告
使用第 3 篇中的 HTML 报告生成脚本,可以生成可视化的测试报告。
09
多走一步:让 Hermes 帮你「造数据 + 洗环境」
列表类用例最怕空表假绿。可以在跑 TC007 之前加一轮对话:
bash📋 复制
请写一个 Python 脚本(Playwright 或 requests,任选其一):登录后新增 5 条测试商品,名称带统一前缀 TEST_AUTO_,价格和库存各不相同,便于后续查询用例断言。并提供测试结束后的清理建议(按名称前缀删除或标记)。
这样查询 / 组合 / 无结果几条用例才不容易变成“嘴上通过”。
10
关键提示词模板(可直接复制)
你可以直接复制使用:
bash📋 复制
【任务拆解】我要对 [系统名称] 的 [功能模块] 进行测试。系统信息:[URL、账号、元素 ID 等]请帮我拆解测试任务为可执行的步骤。【测试用例生成】请把上面的测试步骤转换成可执行的测试用例表格,包含:用例编号、功能模块、用例名称、前置条件、测试步骤、测试数据、预期结果、优先级。【脚本生成】请用 Python + Playwright 为上面的测试用例生成自动化测试脚本。要求:包含登录功能、每个用例独立函数、包含断言、失败截图、输出 JSON 报告、添加详细注释、使用 Page Object 模式。【报告生成】请把 JSON 测试报告转换成 HTML 格式的可视化报告。要求:包含汇总信息、表格展示详情、通过/失败颜色标记、附截图、样式专业。【结果分析】这是测试结果:[粘贴测试数据]请分析测试覆盖是否充分,还有哪些边界场景需要补充,给出改进建议。
11
我建议你重点人审的三处
- TC006(超大价格) :不同产品会「拒绝 / 截断 / 科学计数」,自动化里别写死一种文案,先跟研发对齐规则。
- 查询类用例:列表排序、默认分页会导致“有数据但看不见”,断言尽量绑行内文案或接口返回值,而不是只数
tr。 - 新增与查询耦合:先保证数据工厂脚本稳定,再谈通过率;否则 flakiness 会伪装成“脚本不行”。
12
Q1:元素 ID 找不到怎么办?
A:让 Hermes 帮你生成元素定位脚本:
bash📋 复制
请帮我生成一个 Python 脚本,用 Playwright 打开商品管理页面,打印出所有输入框和按钮的 ID、name、class 等属性,方便我找到正确的元素定位器。
Q2:测试数据怎么准备?
A:让 Hermes 生成测试数据准备脚本:
bash📋 复制
请帮我生成一个 Python 脚本,在测试前先准备测试数据:- 添加 5 个测试商品(名称、价格、库存不同)- 数据要覆盖各种场景(正常价格、边界价格等)
Q3:如何用 Hermes 优化测试脚本?
A:把现有脚本发给 Hermes,让它优化:
bash📋 复制
请帮我优化这个测试脚本:1. 添加重试机制(失败后重试 3 次)2. 添加更详细的日志输出3. 添加测试执行时间统计4. 优化代码结构,提高可读性
13
下一篇预备选题:订单管理(状态流转 + 列表筛选)或工程化加餐(数据工厂、定时报告推飞书群)。留言「订单 / 报表 / 秒杀」里哪个多,我先写哪个。
资源备忘: - Hermes GitHub:github.com/NousResearc…
谢谢你看到这里。
做商品后台测试的同学,留言区丢我你最痛的一点(元素定位 / 数据准备 / 断言 / 报告),我按热度整理成答疑篇。
动手试试
- 先发商品管理页 + 登录方式,要一版「只有表格、没有代码」的用例草案,看和你的直觉差多少。
- 再打开本文「关键提示词模板」,生成可落 Playwright 的第二版。
P.S. 模块越复杂,越要相信:页面即需求入口;平台与 skills 不是对手,是你可以在第二阶段再上的「收纳层」。
本公众号可以搜索testzhouzhougz
如有任何问题可联系周周个人微信:testzhouzhou;