
大家好,我是欢乐马。本篇聊聊 AI 提示词模板库的代码重构优化。
删一行全崩?改一处漏十处?——这就是"能跑但乱"的脚本式代码。今天教你用AI把它重构成"好维护"的代码。
学完你会获得:① 提示词模板(copy就能用)② 豆包+DeepSeek大模型对比③ ⭐ 3个企业级进阶重构场景(鉴权管理/数据驱动/POM框架)
以及,完整源码包+日志+说明+问答,帮你少走弯路少踩坑。
一、你是否也有类似问题
整理近期提问,典型的有:
1. "用自然语言的AI测试,还有必要写好的代码结构吗?" 2. “代码都是硬编码,选择器散落在各个地方,改起来要找半天” 3. ”用例多了之后,代码越写越乱,维护起来头疼“
企业级长期维护的自动化测试项目离不开测试框架。框架搭建第一步不是选工具,而是先把代码结构搞清楚。
本篇实战,分享了提示词模板让豆包和 DeepSeek 分别重构一段"能跑但乱"的测试代码,深入分析对比各自特点,并结合3个典型场景:鉴权管理、数据驱动、POM分层 手把手教你如何借助AI落地代码重构优化。
二、代码重构提示词要点
① AI和人工怎么搭伙
公式:AI重构 → 人工审核业务逻辑 → 微调后用。
② 5个关键要素
1. 明确角色:资深Python代码重构专家 2. 贴原始代码:把要重构的代码直接给AI 3. 明确重构目标:可读性、注释、最佳实践 4. 约束输出格式:完整代码 + 重构说明 5. 强调最佳实践:async with、类型提示等
③ 直接抄:1套提示词模板
你是一位资深的Python代码重构专家。请帮我重构优化以下Playwright自动化测试代码:```python{你的原始代码}重构目标:1. 提高代码可读性和可维护性2. 添加必要的注释3. 遵循Python最佳实践(PEP8)4. 提取重复代码为函数5. 合理的函数和变量命名6. 添加错误处理7. 使用async with上下文管理器请输出重构后的完整代码和重构说明。④ 重构后必做「3条硬标准审核」
1. ✅ 业务逻辑没改 2. ✅ 代码质量合规 3. ✅ 跑得通
三、实战演示:用源码包跑一遍
AI 重构的代码能直接用吗?会不会把业务逻辑改坏?
我用源码包里的一段"能跑但乱"的原始代码,让豆包和 DeepSeek 分别重构,源码包在星球里可下载。
① 原始代码(源码包里自带的 demo)
这段代码是一个完整的 saucedemo 购物流程测试——登录、加购、结账、填写收货信息、完成订单。功能没问题,但代码一看就是"写完就跑,没想过维护"的风格:
import asynciofrom playwright.async_api import async_playwrightasync def test(): p = await async_playwright().start() b = await p.chromium.launch(headless=False) page = await b.new_page() await page.goto('https://www.saucedemo.com') await page.fill('#user-name', 'standard_user') await page.fill('#password', 'secret_sauce') await page.click('#login-button') await page.click('[data-test="add-to-cart-sauce-labs-backpack"]') await page.click('.shopping_cart_link') await page.click('[data-test="checkout"]') await page.fill('[data-test="firstName"]', 'John') await page.fill('[data-test="lastName"]', 'Doe') await page.fill('[data-test="postalCode"]', '12345') await page.click('[data-test="continue"]') await page.click('[data-test="finish"]') await page.wait_for_selector('[data-test="complete-header"]') await b.close() await p.stop()asyncio.run(test())问题一目了然:
• 变量名 p、b看不懂• URL、用户名、密码硬编码 • 选择器散落在代码各处,改一个要找半天 • 没有注释、没有错误处理、没有日志 • 没有 async with资源管理,异常时浏览器进程可能残留
这就是企业级项目里最常见的"脚本式写法"——凌晨三点被叫起来调bug,打开代码一看想骂人的那种。
② 豆包输出(111.82 秒,6728 token)
结论:函数式 + 常量式重构,非常彻底。提取了所有选择器、配置、URL到常量区,加了日志、错误截图、类型提示,代码结构清晰,可维护性大幅提升。
推理过程(关键摘录):
用户给了一段 Playwright 自动化测试代码,需要重构优化……分析原始代码存在的问题:变量命名不清晰(p、b)、硬编码URL和凭据、选择器分散、缺少错误处理和日志、没有使用上下文管理器……重构思路:1)提取常量(URL、选择器、配置) 2)封装通用工具函数(safe_fill等) 3)按业务步骤拆分函数 4)添加日志和错误处理 5)使用上下文管理器管理资源……
豆包关键代码片段:
import asyncioimport loggingfrom datetime import datetimefrom playwright.async_api import async_playwright, Page, TimeoutError# -------------------------- 日志配置 --------------------------logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()])logger = logging.getLogger(__name__)# -------------------------- 全局配置常量 --------------------------HEADLESS_MODE = FalseDEFAULT_TIMEOUT = 30000BASE_URL = "https://www.saucedemo.com"# -------------------------- 页面元素选择器常量 --------------------------SELECTOR_USERNAME_INPUT = "#user-name"SELECTOR_PASSWORD_INPUT = "#password"SELECTOR_LOGIN_BTN = "#login-button"SELECTOR_ADD_BACKPACK_BTN = '[data-test="add-to-cart-sauce-labs-backpack"]'SELECTOR_CART_LINK = ".shopping_cart_link"SELECTOR_CHECKOUT_BTN = '[data-test="checkout"]'SELECTOR_FIRSTNAME_INPUT = '[data-test="firstName"]'SELECTOR_LASTNAME_INPUT = '[data-test="lastName"]'SELECTOR_POSTALCODE_INPUT = '[data-test="postalCode"]'SELECTOR_CONTINUE_BTN = '[data-test="continue"]'SELECTOR_FINISH_BTN = '[data-test="finish"]'SELECTOR_COMPLETE_HEADER = '[data-test="complete-header"]'# -------------------------- 通用工具函数 --------------------------async def safe_fill(page: Page, selector: str, value: str, timeout: int = DEFAULT_TIMEOUT) -> None: """安全填充输入框:自动等待元素可见,统一日志和异常处理""" try: logger.info(f"填充元素【{selector}】,值:{value}") await page.fill(selector, value, timeout=timeout) except TimeoutError: logger.error(f"填充失败:元素【{selector}】等待超时") raise# -------------------------- 业务函数 --------------------------async def login(page: Page, username: str, password: str) -> None: """登录操作""" logger.info("开始登录...") await safe_fill(page, SELECTOR_USERNAME_INPUT, username) await safe_fill(page, SELECTOR_PASSWORD_INPUT, password) await page.click(SELECTOR_LOGIN_BTN) logger.info("登录完成")async def add_item_to_cart(page: Page) -> None: """添加商品到购物车""" logger.info("添加商品到购物车...") await page.click(SELECTOR_ADD_BACKPACK_BTN) await page.click(SELECTOR_CART_LINK) logger.info("商品已加入购物车")代码风格:所有选择器统一放在常量区,页面改了只改一处。safe_fill 通用函数统一处理超时和日志,不用在每个 fill 里重复写 try/except。业务函数按步骤拆分,login()、add_item_to_cart()、checkout() 各司其职。
③ DeepSeek 输出(47.23 秒,2524 token)
结论:面向对象重构,用类封装了所有功能。同样加了日志、错误处理、上下文管理器,代码结构也很清晰,封装性更好。
关键代码片段:
import asyncioimport loggingfrom typing import Optionalfrom playwright.async_api import async_playwright, Page, Browser, Playwrightlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')logger = logging.getLogger(__name__)class SauceDemoTester: """SauceDemo网站自动化测试类""" def __init__(self, headless: bool = False): self.headless = headless self.playwright: Optional[Playwright] = None self.browser: Optional[Browser] = None self.page: Optional[Page] = None async def __aenter__(self): await self.setup() return self async def __aexit__(self, exc_type, exc_val, exc_tb): await self.teardown() async def setup(self) -> None: """设置测试环境""" try: self.playwright = await async_playwright().start() self.browser = await self.playwright.chromium.launch( headless=self.headless) self.page = await self.browser.new_page() logger.info("测试环境设置完成") except Exception as e: logger.error(f"设置测试环境失败: {e}") raise async def teardown(self) -> None: """清理测试环境""" if self.browser: await self.browser.close() if self.playwright: await self.playwright.stop() logger.info("测试环境已清理") async def login(self, username: str, password: str) -> None: """执行登录操作""" await self.page.fill('#user-name', username) await self.page.fill('#password', password) await self.page.click('#login-button') logger.info(f"用户 {username} 登录成功")代码风格:用类把所有功能封装在一起,实现了 __aenter__/__aexit__ 上下文管理器,可以用 async with SauceDemoTester() as tester: 的方式使用,资源自动管理,异常时自动清理。函数命名清晰,每个方法都有 docstring。
④ 两个模型横向对比

async with | __aenter____aexit__ 自实现 | |
safe_fill | ||
| 推荐场景 | ||
| 核心理由 |
⑤ 关键发现
两个模型质量都很高,但思路完全不同——豆包函数式+常量区(选器统一管理,改一处全局生效),DeepSeek面向对象(类封装,异常自动清理)。
选哪个?看你项目风格。
⑥ 人工审核(按3条硬标准)
3条硬标准审核结果:✅ 业务逻辑未改✅ 代码质量合规✅ 跑得通。两份都能直接用,按团队风格选。
⚠️ 踩坑:豆包的 safe_fill 里 timeout 默认值是硬编码,建议改成从 config.yaml 读取。DeepSeek 没把选择器提取到常量区,页面元素多的话建议手动补。
四、从单脚本到企业级框架——3个进阶重构场景
看完了源码包的 AI 对比,你可能会想:学完这些重构技巧,怎么落地到企业级项目里?
5月星球投票里「企业级AI自动化框架搭建」是高票第一的强需求:
鉴权怎么管?多组数据怎么跑?代码量大了怎么分层?
下面用3个进阶场景,把源码包学到的东西往企业级方向延伸一步。
场景1:多环境鉴权管理
背景:重构后的代码把 URL、用户名、密码提到了常量区:
BASE_URL = "https://www.saucedemo.com"TEST_USERNAME = "standard_user"TEST_PASSWORD = "secret_sauce"但真实项目需要同时维护 dev / staging / prod 三套环境,每套环境的 URL、账号、甚至 API token 都不同。把三套配置硬编码在常量区显然不够用。
AI 辅助重构——让 AI 帮你生成一个多环境鉴权管理器:
场景:我在维护 saucedemo 的自动化测试。现有代码: BASE_URL = "https://www.saucedemo.com" TEST_USERNAME = "standard_user" TEST_PASSWORD = "secret_sauce"需求:我需要支持 dev/staging/prod 三个环境,每个环境有独立的 URL、账号凭证、以及一个用于 API 调用的 token。环境通过命令行参数或环境变量切换。请帮我设计一个 ConfigManager 类,要求:1. 支持三种环境(dev/staging/prod),每种环境有独立的 URL 和账号2. 支持从 YAML 文件读取配置,也支持从环境变量覆盖3. 有类型提示和完整的 docstring4. 如果配置文件不存在,能给出明确的错误提示AI 会输出:
import osimport yamlfrom typing import Optional, Dictfrom dataclasses import dataclass, field@dataclassclass Environment: name: str base_url: str username: str password: str api_token: strclass ConfigManager: """多环境配置管理器""" CONFIG_PATHS = [ "./config.yaml", "./config.yml", "~/.playwright/config.yaml", "/etc/playwright/config.yaml", ] def __init__(self, env_name: str = "dev"): self.env_name = os.getenv("PLAYWRIGHT_ENV", env_name) self._config = self._load_config() self.current = self._get_env(self.env_name) def _load_config(self) -> Dict: """逐路径查找配置文件""" for path in self.CONFIG_PATHS: expanded = os.path.expanduser(path) if os.path.exists(expanded): with open(expanded) as f: return yaml.safe_load(f) raise FileNotFoundError( f"未找到配置文件。请在以下路径之一创建:\n" + "\n".join(f" - {p}" for p in self.CONFIG_PATHS) ) def _get_env(self, name: str) -> Environment: """按环境名取配置,支持环境变量覆盖""" env_cfg = self._config["environments"][name] return Environment( name=name, base_url=os.getenv("BASE_URL", env_cfg["base_url"]), username=os.getenv("TEST_USERNAME", env_cfg["username"]), password=os.getenv("TEST_PASSWORD", env_cfg["password"]), api_token=os.getenv("API_TOKEN", env_cfg.get("api_token", "")), )配套的 config.yaml:
environments: dev: base_url: "https://dev.saucedemo.com" username: "dev_user" password: "dev_pass" api_token: "dev-token-xxx" staging: base_url: "https://staging.saucedemo.com" username: "staging_user" password: "staging_pass" api_token: "staging-token-xxx" prod: base_url: "https://www.saucedemo.com" username: "standard_user" password: "secret_sauce" api_token: "" # 生产环境建议从 CI 密钥获取改造后用起来的写法:
# 原来:BASE_URL = "https://www.saucedemo.com"# 现在:config = ConfigManager(env_name="staging") # 或从环境变量读取# 在测试脚本里:async with SauceDemoTester(config=config) as tester: await tester.login(config.current.username, config.current.password)和投票缺口的关联:多环境鉴权管理是企业级框架的基础设施。上面的 ConfigManager 只是一个起点——你还可以往里面加 token 自动续期、cookie 持久化、多账号池等功能。源码包学到"提取常量为配置",到这里扩展为"多环境感知的管理器",这就是从单脚本到企业级框架的第一步。
场景2:测试数据驱动
背景:重构后的 login() 函数只跑一组账号:
async def test_standard_user(): async with SauceDemoTester() as tester: await tester.goto() await tester.login("standard_user", "secret_sauce") # 验证标准用户能看到所有商品但实际测试需要验证多种用户类型——普通用户、问题用户(页面显示异常)、锁定用户(登录即被拦截)、性能用户(大量数据的响应速度)。每类用户的期望行为不同,手工复制几份相似代码就是典型的"散落式维护"。
AI 辅助重构——让 AI 帮你转为参数化测试:
场景:我用 pytest + Playwright 测试 saucedemo 的登录功能。现有代码是一个 test_standard_user 函数,只测试标准用户。需求:我需要测试以下4类用户,每类用户的期望结果不同:1. standard_user / secret_sauce → 登录成功,显示商品列表2. locked_out_user / secret_sauce → 登录失败,显示锁定错误提示3. problem_user / secret_sauce → 登录成功,但商品图片显示异常4. performance_glitch_user / secret_sauce → 登录成功,但页面加载缓慢请帮我:1. 用 pytest 的 @pytest.mark.parametrize 实现数据驱动2. 测试数据统一管理(建议用外部文件或常量区)3. 每条用例独立验证期望结果4. 输出完整的测试代码文件AI 会输出:
import pytestfrom playwright.async_api import async_playwright# 测试数据集TEST_USERS = [ pytest.param( "standard_user", "secret_sauce", True, "inventory_list", id="standard_user-正常登录" ), pytest.param( "locked_out_user", "secret_sauce", False, "error-message", id="locked_out_user-登录被锁定" ), pytest.param( "problem_user", "secret_sauce", True, "inventory_list", id="problem_user-登录成功图片异常" ), pytest.param( "performance_glitch_user", "secret_sauce", True, "inventory_list", marks=pytest.mark.slow, # 慢速用户单独标记 id="performance_glitch_user-登录慢" ),]class TestLoginDataDriven: """数据驱动:登录测试""" @pytest.mark.parametrize( "username,password,expect_success,expect_selector", TEST_USERS) async def test_login_users(self, page, username, password, expect_success, expect_selector): """用多组数据验证登录行为""" await page.goto("https://www.saucedemo.com") await page.fill("#user-name", username) await page.fill("#password", password) await page.click("#login-button") if expect_success: await page.wait_for_selector(f".{expect_selector}") assert await page.is_visible(f".{expect_selector}") else: await page.wait_for_selector(f".{expect_selector}") error_text = await page.text_content( '[data-test="error"]') assert "locked" in error_text.lower()pytest 运行结果:
test_login.py::TestLoginDataDriven::test_login_users[standard_user-正常登录] ✓test_login.py::TestLoginDataDriven::test_login_users[locked_out_user-登录被锁定] ✓test_login.py::TestLoginDataDriven::test_login_users[problem_user-登录成功图片异常] ✓test_login.py::TestLoginDataDriven::test_login_users[performance_glitch_user-登录慢] ⚠ 慢和投票缺口的关联:数据驱动是中级到企业级的分水岭。从"一组数据跑一次"到"多组数据覆盖多种用户场景",可维护性提升一个量级。投票③里星友问的"用例多了之后代码越写越乱"——答案就在这里:用参数化替代复制粘贴,用数据集管理替代零散硬编码。
从源码包到这个场景的演进路径:
源码包的原始代码 → 一组数据硬编码源码包重构之后 → 提取到常量区(一组数据)场景2扩展实战 → 多组数据参数化(数据驱动)场景3:从函数到POM分层
背景:投票③里星友问的"用例多了之后代码越写越乱",行业标准方案是 POM(Page Object Model)——每个页面一个类,类里放这个页面的定位器和操作逻辑,测试用例只调用类方法,不直接操作元素。
源码包02playwright_pytest_framework就是一个完整POM框架,下面用AI重构符合POM的代码到框架中:
AI 辅助迁移——让 AI 帮你拆分为页面对象:
场景:我有一个 SauceDemoTester 类,里面包含了登录、商品列表操作、购物车操作三个功能,放在一个文件里。我需要重构为POM模式,拆分到三个文件中:1. LoginPage — 登录页面的定位器和操作2. InventoryPage — 商品列表页面的定位器和操作(加购、查看购物车)3. CheckoutPage — 结账流程的定位器和操作(填写信息、确认、完成)框架要求(参考源码包06):- 每个类继承 BasePage- BasePage 提供 navigate / fill / click / wait 等基础方法- 定位器统一放在类变量中,用 data-test 属性优先- 类方法返回 self 或新的 Page 对象,方便链式调用请生成三个完整的 Page Object 类代码。AI 会输出(以 LoginPage 为例):
"""pages/login_page.py"""from pages.base_page import BasePageclass LoginPage(BasePage): """登录页面对象""" # 定位器(优先 data-test,其次 id) USERNAME_INPUT = '#user-name' PASSWORD_INPUT = '#password' LOGIN_BUTTON = '#login-button' ERROR_MESSAGE = '[data-test="error"]' def load(self) -> "LoginPage": """导航到登录页""" self.navigate(self.config.base_url) return self def login(self, username: str = None, password: str = None) -> "InventoryPage": """执行登录,成功后返回商品列表页""" username = username or self.config.current.username password = password or self.config.current.password self.fill(self.USERNAME_INPUT, username) self.fill(self.PASSWORD_INPUT, password) self.click(self.LOGIN_BUTTON) # 导入在此避免循环引用 from pages.inventory_page import InventoryPage return InventoryPage(self.page, self.config) def get_error_message(self) -> str: """获取登录失败错误提示""" return self.get_text(self.ERROR_MESSAGE)配套的 BasePage 基类(框架已有,这里展示核心方法):
"""pages/base_page.py"""class BasePage: def __init__(self, page, config=None): self.page = page self.config = config def navigate(self, url): self.page.goto(url, wait_until="networkidle") return self def fill(self, locator, value): self.page.fill(locator, value) return self def click(self, locator): self.page.click(locator) return self def get_text(self, locator) -> str: return self.page.text_content(locator) def screenshot(self, name: str): self.page.screenshot(path=f"screenshots/{name}.png") return self最终测试用例:
"""tests/test_checkout_flow.py"""class TestCheckoutFlow: def test_full_checkout(self, logged_in_page): """完整购物流程测试""" # logged_in_page fixture 已经处理好了登录 inventory = InventoryPage(logged_in_page) checkout = ( inventory .add_item_to_cart() .go_to_cart() .proceed_to_checkout() ) checkout.fill_shipping_info("John", "Doe", "12345") checkout.complete_order() assert checkout.is_order_complete()和投票缺口的关联:POM 是企业级框架的核心骨架。从源码包里的单脚本 → AI重构后的函数封装 → 场景2的数据驱动 → 再到这里的页面对象分层,这条演进路径就是投票③「企业级AI自动化框架搭建」从0建起的全过程。
三个场景的演进路径总图
源码包原始代码 AI重构后 扩展场景 企业级框架───────────────── ─────────────── ──────────────── ─────────────────一个文件、一个函数 常量区管理选择器 场景1: ConfigManager 鉴权管理器硬编码URL/账号 独立业务函数 多环境YAML配置 token自动续期 cookie持久化无数据驱动 单一数据源 场景2: @parametrize 数据驱动引擎 多用户类型覆盖 外部数据文件 CI参数注入无页面分层 类封装/SauceDemoTester 场景3: POM拆分 POM框架 继承BasePage 组件化页面对象 多项目复用小结:源码包教会你"怎么把一段乱代码写规范";这3个场景教会你"规范之后怎么往上搭架子"——从鉴权管理到数据驱动到POM分层,每一步都是企业级框架的组成部分。
五、FAQ
Q1: AI重构后的代码风格不符合我团队的规范怎么办?
在提示词里加团队的代码规范说明,或者把一段符合团队规范的代码放在提示词里,让 AI 参考你团队的规范来重构。
Q2: AI重构时会不会改变业务逻辑?
在提示词里特别强调「不要改变业务逻辑」,并且重构后人工一定要审核。本文的进阶模板已经把这条排在重构目标第1位。
Q3: AI重构的代码我不满意,可以反复让AI重构吗?
可以,把你不满意的地方告诉 AI,让它再重构一次。或者换个提示词再试一次——AI 的输出受提示词影响很大,同样的代码用不同的约束条件,重构结果可能完全不同。
六、作业
1. 必做:重构自己的一段乱代码 → 按团队规范微调 → 跑通审核通过 2. 进阶(选一个落地): • 多环境测试 → 场景1:ConfigManager(⭐简单) • 多组数据覆盖 → 场景2:参数化驱动(⭐⭐中等) • 规划框架搭建 → 场景3:POM拆分(⭐⭐⭐复杂) 3. 选做:合并两个模型的优势——豆包的常量区 + DeepSeek的类封装
七、总结
• 前半部分:代码重构的提示词模板——5 个关键要素 + 基础/进阶两套模板,把原始代码贴进去就能用。两个模型对比:豆包函数式(选择器管理强)vs DeepSeek 面向对象(封装性好)。 • 后半部分(进阶场景):从单脚本重构延伸到企业级框架的3个缺口——多环境鉴权管理(场景1)、数据驱动(场景2)、POM分层(场景3)。每一段都是源码包学到的知识的下一级台阶。
学完重构之后的进阶路径——鉴权管理→数据驱动→POM分层,就是投票「企业级框架」三个缺口的逐层搭建。
框架不是一天搭成的,但重构是第一天就要做的事。
以上全套(可运行源码、提示词模板、完整重构日志对比分析)均已上知识星球,大家可自取。
源码包怎么领取?关注本公众号,点“私信”

在对话框回复:
• 【提示词模版】可获得领取方式

下期预告
AI 提示词系列第 6 篇——报错分析修复:让 AI 帮你分析测试失败原因,给出修复方案。
免费学,付费练,一文一码,就找欢乐马。
夜雨聆风