简介:Katalon Recorder-脚本录制工具.zip 面向需要提升Web测试效率的测试工程师、Web开发者及自动化测试初学者,聚焦Chrome浏览器环境下的脚本录制与回放,帮助降低Selenium WebDriver脚本编写门槛。压缩包共4个文件,以2个crx浏览器扩展和2个html说明文档为主,体积约3.95MB,扩展承担录制与回放等核心功能,说明文档则提供安装及使用指引,结构简洁便于查阅。该资源已有1519人学习下载,适合希望快速上手Web自动化测试的读者参考。录制浏览器操作即可生成可编辑的测试步骤,并能在内置编辑器中补充断言、循环等逻辑,便于完成从手工操作到脚本化验证的过渡;随附文档可辅助扩展部署与基本使用,附带的浏览器增强扩展还可优化新标签页与书签管理体验。整体适合作为自动化测试入门、用例录制及日常脚本沉淀的轻量工具包。
1. 录制的价值不在脚本本身:Katalon Recorder 把定位器试错压缩到十分钟
很多人第一次打开 Katalon Recorder 这类脚本录制工具,会把它当成“点一遍就能生成自动化用例”的捷径,结果录完回放红一片。我的看法相反:它的价值不在生成那几行脚本,而在于把“元素到底该怎么定位”这段最耗时的试错压缩到十分钟以内。你手动点一遍,它把 click、type、select、assert 这些动作和候选定位器一起记下来,你再去改定位器、补等待、加断言,比从空白文件里猜 id 快得多。适合刚接手 Web 自动化、页面元素命名混乱、又需要快速铺开回归用例的团队;不适合指望它录完就无人值守跑通的人。
2. 解压之后先认形态:扩展加载、权限与内网页面的三条边界
拿到 Katalon Recorder 的压缩包,第一反应往往是双击找安装程序,但浏览器扩展不是 exe。它要么以商店安装包的形式存在,要么以未打包目录的形式存在,后者更适合内网、离线、固定版本复现。先认清形态再动手,能省掉后面很多“为什么按钮是灰的”的排查。这个工具本质上是注入到页面里的录制器,它要读 DOM、监听事件、回写定位器,所以权限给得比较宽,这也是为什么我建议把它装在一个专用浏览器配置里,而不是日常刷页面的那个窗口。
2.1 先分辨扩展形态:未打包加载与商店安装的差异
未打包加载和商店安装最大的差别不是功能,而是更新和签名。商店安装由浏览器负责版本管理,扩展清单版本升级后可能某天自动变化;未打包加载则是你解压什么版本就跑什么版本,适合把一套回归脚本固定在某个浏览器版本上做验证。缺点是每次启动可能提示“开发者模式扩展”,部分企业策略会直接禁用未打包扩展。我的习惯是:做定位器试验、内网页面录制、旧脚本复现时用未打包目录;长期日常使用再考虑商店版本。两者不要混在同一个浏览器配置里,否则扩展 ID 和存储会打架,录制列表看起来会莫名其妙少几条。
加载时最容易踩的坑是选错目录层级。扩展管理页要求选中的目录里直接能看到清单文件,如果你选的是压缩包解压后的上一级,页面会提示找不到清单。另一个坑是解压工具把目录多套了一层,表面看文件夹名对,点进去还有一层同名目录。我一般先在文件管理器里确认清单文件就在当前层,再去浏览器里加载。加载成功后先别急着录业务页面,打开一个本地静态页,点两下按钮,看录制列表有没有生成 click 步骤;没有生成就说明注入没成功,先查扩展是否被策略禁用,再查页面是不是浏览器内部页或扩展商店页,这两类页面本来就不允许注入。
# 用独立用户目录启动 Chromium 内核浏览器,把录制扩展和日常配置隔离 # 参数说明: # --user-data-dir 指定独立配置目录,避免污染日常书签和登录态 # --disable-extensions-except 只允许指定目录的扩展运行,减少干扰 # --load-extension 加载未打包扩展目录,目录里必须直接包含清单文件 chromium \ --user-data-dir="$HOME/.recorder-profile" \ --disable-extensions-except="$HOME/ext/katalon-recorder" \ --load-extension="$HOME/ext/katalon-recorder"这段命令的作用不是“安装”,而是每次用同一套干净配置启动浏览器。--user-data-dir让录制产生的本地存储、下载文件、登录态都落在独立目录,出问题可以直接删目录重来,不会影响你日常浏览器。--disable-extensions-except和--load-extension要指向同一个扩展目录,路径里不要带中文和空格,Windows 下用反斜杠时注意转义。如果你用的是 Firefox,加载方式不同,但思路一样:专用配置、固定扩展目录、先验证注入再录业务。参数不用背,记住“独立配置 + 固定目录”这两个点就够了。
2.2 权限模型:为什么它要读所有页面,以及怎么把口子收小
录制器要求“读取和更改所有网站上的数据”,看起来吓人,但原理不复杂:它要在每个页面里注入脚本,监听点击、输入、选择事件,还要读取元素属性生成定位器。如果只允许特定域名,跨域 iframe、新标签页、跳转后的页面就可能录不到。这不是它想偷数据,而是录制这种工作方式决定的。理解这一点后,正确的做法不是反复点“拒绝”,而是把使用范围收小:专用浏览器配置、只登录测试环境、不在里面保存生产账号、录完就关掉那个窗口。对公网页面也一样,录制时尽量用测试账号,别把真实订单和真实用户数据带进脚本。
我一般会把录制浏览器和日常浏览器分开两个图标,录制浏览器不装密码管理器、不登个人邮箱。扩展的下载权限也要注意,录制过程中如果触发文件下载,浏览器会把文件落到默认下载目录,批量回放时可能覆盖同名文件。可以在专用配置里把下载目录设成固定临时目录,每次跑完清空。还有一点,录制器生成的脚本里可能带上页面上的可见文本,如果测试页面里有手机号、地址这类内容,导出后要检查一遍,别把测试数据带进代码库。权限收不窄,但使用边界可以收窄,这是两回事。
2.3 内网与离线页面的可用边界:不是所有页面都适合录
内网页面常见的三个拦路虎是自签证书、内容安全策略和虚拟化渲染。自签证书会让浏览器先弹拦截页,录制器本身不解决证书信任问题,你得先让浏览器正常打开页面,再谈录制。内容安全策略可能限制内联脚本注入,表现是扩展图标亮着但录制列表不增加步骤,这时候换一个页面验证,确认是页面策略问题而不是扩展没装好。虚拟化渲染指的是列表、表格用 canvas 或大量动态节点拼出来,DOM 里没有稳定的按钮和输入框,录制器只能记下坐标点击,回放时窗口一变化就偏。这类页面我一般不硬录,先找页面有没有提供可访问的隐藏输入框或接口,再决定用脚本还是用录制。
离线页面也不是都能录。浏览器内部页、扩展管理页、部分 PDF 预览页禁止注入,录不了是正常的。单页应用的路由跳转如果没触发完整页面加载,录制器可能把跳转前后的步骤混在一条记录里,回放时等待条件不够就会找不到元素。我的判断标准很简单:手动操作时页面地址变了、元素出现有明显延迟、或者关键控件在 iframe 里,这三种情况先别急着批量录,先拿一条最短路径试通,再决定要不要继续。内网环境还要注意浏览器版本,太新的浏览器可能不再支持旧清单版本的扩展,表现是加载成功但不注入;太旧的浏览器又可能缺少现代定位器支持。固定一个能跑通的浏览器版本,比每次追新更省事。
3. 从点击流到可读脚本:定位器优先级、断言与导出代码的改造点
录制出来的脚本能不能用,七成看定位器,两成看等待,一成看断言。Katalon Recorder 录制时会自动选一个它认为合适的定位器,但“它认为合适”和“下个版本还稳定”是两回事。我通常把录制结果当成候选清单,而不是最终答案:先看它选了 id 还是 xpath,再把动态部分改成稳定属性,最后补上验证点。这个过程不需要把整条脚本重写,但需要你在导出前过一遍定位器列,把明显带随机串的挑出来。下面这套顺序是我用得最顺的,先清状态,再定定位器,再补断言,最后改导出代码。
3.1 录制前清状态:缓存、登录态与初始页面
录制前不清理状态,后面排查会非常痛苦。最常见的情况是:第一次录的时候页面已经登录,脚本里没有登录步骤;换台机器回放,直接跳到业务页,结果被重定向到登录页,所有后续步骤全红。我的做法是每次录制前用专用配置打开一个干净窗口,手动走一遍“从登录到目标页”的完整路径,确认中间没有一次性弹窗、没有引导蒙层、没有随机推荐浮层,再开始录。窗口大小也要固定,响应式页面在窄窗口下会把按钮收进菜单,录制器记下的点击目标在宽窗口回放时可能不可见。语言和时区也尽量固定,日期控件和排序结果对这两项很敏感。
还有一个容易被忽略的点:浏览器自动填充。录制时输入框可能被自动填上旧账号,脚本里记下的输入值就成了错的。录制前把自动填充关掉,或者用无痕式独立配置。页面缓存也会影响结果,改了前端静态资源后,旧缓存可能让录制时的 DOM 和回放时的 DOM 不一致。我一般在录制前强制刷新一次,确认关键元素在开发者工具里能看到稳定属性。做完这些再点录制,后面能少很多“昨天还能跑”的玄学问题。
3.2 定位器优先级:id、name、css、xpath 的实测顺序
定位器没有绝对优劣,只有稳定性和可读性的取舍。我实际排序是:稳定的 id 优先,其次是 name,再是 css 选择器,最后才是 xpath。id 最短也最快,但很多前端框架生成的 id 带随机串,今天id=btn-9f3a,明天就变成id=btn-77c1,这种 id 不能直接用。name 在表单里比较稳定,适合输入框和单选组。css 选择器适合用># 由录制脚本改造后的 Selenium 骨架:函数化、显式等待、参数外置 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 def make_driver(): options = webdriver.ChromeOptions() # 调试录制脚本时先不要开无头,肉眼观察页面状态比看日志快 # options.add_argument("--headless=new") driver = webdriver.Chrome(options=options) driver.set_window_size(1440, 900) # 固定窗口,避免响应式布局把按钮藏进菜单 return driver def login(driver, base_url, username, password): wait = WebDriverWait(driver, 10) # 10 秒是内网系统的常用上限,公网可加到 15 driver.get(f"{base_url}/login") wait.until(EC.presence_of_element_located((By.ID, "username"))).send_keys(username) driver.find_element(By.ID, "password").send_keys(password) driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click() # 登录后的稳定标志:用户菜单出现,比等待 URL 变化更可靠 wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='user-menu']"))) def search(driver, keyword, expect_count): wait = WebDriverWait(driver, 10) box = wait.until(EC.element_to_be_clickable((By.NAME, "q"))) box.clear() box.send_keys(keyword) driver.find_element(By.CSS_SELECTOR, "button[data-testid='search']").click() # 等待结果区域出现,而不是 sleep 固定秒数 rows = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".result-row"))) assert len(rows) >= expect_count, f"结果条数不足:{len(rows)} < {expect_count}"
这段代码的逻辑说明:make_driver负责生命周期和窗口尺寸,login和search各自封装一个业务动作组,等待条件都绑在具体元素上。参数说明:WebDriverWait(driver, 10)里的 10 是最大等待秒数,不是固定睡眠;presence_of_element_located只要求元素在 DOM 里,visibility_of_element_located还要求可见,登录后的菜单用后者更稳;set_window_size(1440, 900)是为了让响应式页面保持桌面布局,如果你的系统在 1366 宽度下才显示完整表格,就改成对应值。导出代码里常见的time.sleep(3)要全部找出来替换,否则批量跑起来会又慢又飘。
4. 数据驱动与批量回放:CSV 参数化、等待策略和日志定位
一条录制脚本只能证明一个场景,真实回归需要的是同一套动作跑多组数据。Katalon Recorder 本身支持数据驱动,但导出到代码后,用 CSV 或 pytest 参数化更灵活。这一章的重点不是“怎么循环”,而是循环起来之后怎么让失败可定位。批量回放最怕黑匣子:跑完只告诉你失败了,不告诉你哪条数据、哪一步、当时页面长什么样。把数据、等待、日志三件事拆开处理,批量回放才有意义。
4.1 用 CSV 把一条脚本扩成 N 条用例
CSV 的好处是业务人员也能改数据,坏处是编码和空值容易出问题。我一般用 UTF-8 带 BOM 保存,避免表格软件打开乱码;字段名固定为case_id、url、username、password、keyword、expect_count,每行一条用例。代码里用csv.DictReader读取,按case_id生成日志前缀,失败时截图文件名也带case_id,这样一眼能看出是哪条数据挂了。
# 读取 CSV 并逐行回放,失败时截图并按 case_id 命名 import csv from pathlib import Path from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def load_cases(csv_path): # utf-8-sig 兼容表格软件保存时带 BOM 的情况 with open(csv_path, newline="", encoding="utf-8-sig") as f: return list(csv.DictReader(f)) def run_case(driver, row, shot_dir="shots"): wait = WebDriverWait(driver, 10) driver.get(row["url"]) wait.until(EC.presence_of_element_located((By.NAME, "q"))).send_keys(row["keyword"]) driver.find_element(By.CSS_SELECTOR, "button[data-testid='search']").click() rows = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".result-row"))) expect = int(row["expect_count"]) if len(rows) < expect: Path(shot_dir).mkdir(exist_ok=True) driver.save_screenshot(f"{shot_dir}/{row['case_id']}_count_{len(rows)}.png") raise AssertionError(f"{row['case_id']} 结果不足:{len(rows)} < {expect}")逻辑说明:load_cases只负责读数据,run_case只负责执行一条,失败时先截图再抛异常,调用方可以决定继续下一条还是中止。参数说明:expect_count要转成整数再比较,CSV 里读出来都是字符串;截图目录用相对路径时,注意 pytest 或命令行的工作目录,最好统一用绝对路径;WebDriverWait的超时时间可以按环境配成变量,内网慢的时候统一调大,而不是每条用例里散落不同数字。CSV 里的空值要提前校验,keyword为空时send_keys不会报错,但搜索结果会变成全量,断言就会误判。
4.2 等待命令的参数:timeout、轮询与失败截图
录制器里的等待命令和导出后的显式等待不是一回事。录制器常见的有waitForElementPresent、waitForVisible、waitForText,参数一般是定位器和超时毫秒数;导出后对应的是WebDriverWait加条件函数,超时单位变成秒,还可以设置轮询间隔。我的原则是:页面跳转用元素出现做条件,不用固定睡眠;列表加载用“行数达到预期”做条件,不用“第一行出现”;文件下载和异步导出这类没有 DOM 信号的动作,才用有限次的轮询检查文件是否存在。
| 等待方式 | 关键参数 | 适用场景 | 失败时先看什么 |
|---|---|---|---|
| waitForElementPresent | 定位器、超时毫秒 | 元素早晚会出现 | 定位器是否命中、页面是否跳转 |
| waitForVisible | 定位器、超时毫秒 | 元素出现但被遮挡 | 是否有蒙层、是否在视口外 |
| waitForText | 定位器、文本、超时 | 提示语、状态变化 | 文本是否带日期或空格差异 |
| 显式等待条件 | 超时秒、轮询间隔 | 导出代码后的标准做法 | 条件函数是否选错 |
| 固定 pause | 毫秒 | 仅用于调试观察 | 批量回放时全部替换 |
固定pause不是不能用,但只能用于调试。批量回放里每步都 pause 两秒,一百步就是两百秒,而且页面快的时候白等,页面慢的时候还是不够。超时时间也不要拍脑袋,内网系统第一次加载可能慢,后续操作快,可以给登录和首屏设置更长超时,业务操作设置短一些。失败截图要带步骤名或case_id,不要只截一张全屏图,否则回看时根本不知道停在哪一步。
4.3 批量回放与日志:从黑匣子到可定位
批量回放最需要的是“失败现场”。我一般开三个东西:控制台日志、失败截图、当前 URL。控制台日志里记录case_id、步骤名、定位器、耗时;截图记录页面状态;URL 记录是否跳到了错误页或登录页。Katalon Recorder 自己的日志面板也能看步骤执行结果,但批量跑的时候还是导出到代码里加日志更灵活。日志不要只写“失败”,要写“哪个定位器在多少秒内没找到,当前页面标题是什么”。
用 pytest 参数化可以把 CSV 和用例管理结合起来,失败用例会单独标记,重跑也方便。下面是一个最小示例,重点看参数化入口和失败重试的边界:重试只适合网络抖动导致的超时,不适合定位器错误,定位器错了重试多少次都没用。
# pytest 参数化入口:每条 CSV 数据生成一个独立用例,失败可单独重跑 import pytest from selenium import webdriver def pytest_generate_tests(metafunc): if "row" in metafunc.fixturenames: rows = load_cases("cases.csv") metafunc.parametrize("row", rows, ids=[r["case_id"] for r in rows]) @pytest.fixture def driver(): d = webdriver.Chrome() d.set_window_size(1440, 900) yield d d.quit() def test_search(driver, row): run_case(driver, row)逻辑说明:pytest_generate_tests把 CSV 行注入成参数,ids用case_id,报告里就能直接看到哪条数据失败;driverfixture 负责每条用例后退出浏览器,避免状态串味。参数说明:如果用例很多,每条都启停浏览器会很慢,可以改成 session 级 fixture 加手动清理登录态,但要注意 Cookie 和本地存储的隔离;重试插件不要全局开,只给明确的超时异常加一次重试。批量回放跑完后,先看失败列表里有没有集中在一个定位器上,集中失败通常是页面改版,分散失败通常是数据或等待问题。
5. 避坑与排查:五个现场翻车记录与对应修法
录制工具用久了,你会发现大部分失败不是工具本身的问题,而是页面状态、定位器和浏览器上下文没对齐。下面五条是我在项目里反复遇到的,按“现象 → 原因 → 解决”写,每条都尽量落到可操作的修法。不要把每条都当成理论,下次回放红的时候按顺序对一遍,能省不少时间。
5.1 动态 id 导致回放失败
现象:录制时明明点的是“提交”按钮,回放时报找不到元素,开发者工具里看 id 变成了一串带随机字符的值。原因:前端框架在渲染时生成临时 id,录制器恰好抓到了那一刻的值,刷新页面后 id 重新生成。解决:不要用带数字串的 id,改用稳定的业务属性。如果按钮有style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />