尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Selenium Web自动化测试实战:从环境搭建到PageObject框架设计

Selenium Web自动化测试实战:从环境搭建到PageObject框架设计 简介本资源是一套面向自动化测试工程师、QA人员及Python测试开发初学者的Selenium实战框架集成包系统解决Web UI自动化测试中WebDriver配置、元素定位失效、异步加载失败、多浏览器兼容性验证及测试用例维护成本高等核心痛点。压缩包共含多个模块化工程文件以Python脚本为主辅以配置文件、测试数据样例CSV/Excel及Page Object类定义文件整体大小77.45MB结构清晰便于按需抽取复用。资源已获28人学习下载内容覆盖Chrome/Firefox跨浏览器驱动配置、ID/XPath/CSS Selector等八种定位策略对比应用、显式等待与隐式等待的典型场景编码示例、基于参数化实现的数据驱动测试模板以及符合行业规范的Page Object分层设计案例——所有代码均经实际项目验证可直接运行调试显著降低入门门槛并提升测试脚本健壮性与可维护性。 做Web自动化测试这些年Selenium是我用得最多也最熟悉的一套工具。前两天整理工作盘翻出了一个已经打包归档的自动化测试框架项目里面正好包含了从Selenium WebDriver安装配置、元素定位、等待机制到PageObject设计模式、数据驱动测试、跨浏览器测试的完整代码和实战案例。借着这次整理我干脆把当初踩过的坑、做过的方案选型以及几个高频问题的排查方法一并梳理出来做成一篇可以照着抄的实战笔记。这套框架能做什么一句话讲清楚把Web UI层面的重复性验证交给脚本去跑覆盖日常回归测试、多浏览器兼容性验证甚至延伸做数据采集。它适合三类人看刚接触自动化没多久的测试工程师、正在从零搭建团队测试框架的测试开发以及想用Selenium解决实际重复劳动问题的开发者。不管你属于哪一类这篇文章都会尽量把原理讲透、把步骤写全让你看完能直接上手。1. 先聊聊这套框架的整体设计思路1.1 为什么选Selenium而不是其他工具市面上的Web自动化工具其实不少Playwright、Cypress这两年的势头也很猛生而带自动等待、自带调试工具体验确实好。但我在实际项目中最终还是把Selenium作为主力框架原因很朴素生态兼容性。Selenium WebDriver本身就是W3C的标准协议各大浏览器厂商原生支持这意味着同一套脚本理论上可以无缝跑在Chrome、Edge、Firefox、Safari上。很多企业内部的业务系统尤其是银行、政务、制造业的老系统浏览器环境非常固定而且版本老旧只有Selenium能稳定驱动。再加上Python、Java、C#、Ruby都有官方客户端团队用什么语言都能接招人也容易。另外Selenium的学习资料足够厚遇到问题搜一下基本都有答案。新工具再好踩坑时找不到解决方案对团队来说就是成本。所以我的结论是小团队快速构建框架Selenium依然是性价比最高的选择。1.2 框架分层把代码拆成一眼就能看懂的结构这套框架如果只有一个核心设计理念那就是分层。很多刚入门的朋友写自动化喜欢把所有代码塞进一个文件里登录、点击、断言全写在一起。脚本少的时候没问题但用例一多维护成本会指数级上升。我用的分层结构是这样project/ ├── config/ │ ├── base_config.py # 全局配置环境地址、浏览器类型、超时时间 │ └── test_data.yaml # 测试数据数据驱动用 ├── pages/ │ ├── login_page.py # 页面对象层 │ └── home_page.py ├── tests/ │ ├── test_login.py # 测试用例层 │ └── conftest.py # pytest夹具初始化和清理 ├── utils/ │ ├── driver_factory.py # 浏览器驱动工厂 │ └── wait_utils.py # 显式等待封装 └── reports/ # 测试报告输出分层带来最直接的好处元素定位变了只改pages目录下的对应文件测试数据变了只改yaml浏览器换了只改driver_factory。测试用例本身几乎不动维护成本被压到最低。后面每一节讲的都是这个骨架里的具体零件我们一个一个拆开看。2. 环境搭建与WebDriver安装配置最容易翻车的一关2.1 装环境前必须搞懂的两个关键点很多新手在环境搭建阶段就卡住了装了Selenium库脚本一跑就报错报什么错都有。这里核心是两个问题没搞清楚第一Selenium库和浏览器驱动是两个东西。pip install selenium装的是Python客户端库它负责把你的代码翻译成WebDriver协议的命令。真正去驱动浏览器的是各个浏览器对应的Driver程序Chrome叫chromedriverEdge叫msedgedriverFirefox叫geckodriver。缺了任何一个脚本都跑不起来。第二Driver版本和浏览器版本必须匹配。这一点是重灾区。Chrome升级了chromedriver没跟上启动浏览器时就会报session not created或者直接闪退。匹配规则很简单chromedriver的大版本号要和Chrome的大版本号一致。比如你的Chrome是120.0.xxxx那就必须下载120开头的chromedriver小版本号可以不完全一致但大版本一定不能错。2.2 三种安装浏览器驱动的正确方式我自己在项目里用过三种方式从手动到全自动都有看你的场景选择方式一手动下载放到Python目录或系统PATH里。这种方式最传统去官方源下载对应平台的driver压缩包解压后放到/usr/local/bin这种目录或者直接扔到Python Scripts目录下。优点是可控缺点是每次浏览器升级都要手动维护一次团队协作时还需要大家统一环境。方式二用webdriver-manager库自动管理。我目前最推荐这种方式代码里指定一下运行时会自动检测浏览器版本并下载匹配的driver。from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice)首次运行会下载driver到本地缓存之后再运行直接用缓存不再重复下载。团队里每个人装一遍就能跑不用手动配置环境变量。方式三Selenium 4.6以上自带的Selenium Manager。从4.6版本开始Selenium内置了Selenium Manager当你的代码没有显式指定driver路径时它会自动寻找并下载匹配的driver。也就是说最简写法webdriver.Chrome()在4.6以上的版本就能直接跑通。这个功能在国内某些环境可能因为网络问题不太稳定如果下载失败回退到webdriver-manager方案就好。2.3 特殊环境安装问题Edge闪退与国产系统部署热词里出现的selenium控制edge会闪退和麒麟安装selenium都是环境问题的高频现象。先讲Edge闪退这个我遇到太多次了。Edge闪退最常见的原因是用了Chrome的driver去驱动Edge。虽然Edge是Chromium内核但它的driver名字是msedgedriver协议实现和chromedriver并不完全互通。你写webdriver.Chrome()去控制Edge大概率闪退。正确做法是安装Edge专属driver并且和Edge浏览器版本保持一致。还有一个隐蔽原因是options参数冲突。如果代码里添加了--headless、--disable-gpu这类参数但参数写法和当前版本不兼容也会导致闪退。排查思路是先去掉所有options用最干净的方式启动能跑起来再逐步加参数定位到具体是哪个参数出的问题。至于麒麟系统本质是Linux环境下的安装核心注意点有两个一是要下载Linux版本的chromedriver二是麒麟系统可能有x86和ARM飞腾/鲲鹏两种架构driver的架构必须和系统架构一致下载后用chmod x赋予执行权限。装好之后就是标准的Selenium用法没有特殊之处。这类国产化环境我踩过的最大教训是不要想当然用Windows的driver一定要先确认系统架构。3. 元素定位策略八种定位方式的取舍与实战技巧3.1 八种定位方式怎么选Selenium官方提供了八种元素定位方式id、name、class_name、tag_name、link_text、partial_link_text、xpath、css_selector。刚接触的人容易犯的选择困难症是到底该用哪个我的建议是有一个优先级判断按顺序尝试优先级定位方式优点缺点适用场景1id唯一、速度快部分元素没有id有id就用id2name唯一性较好可能重复表单元素3css_selector速度快、语法简洁复杂层级写起来长没有id/name时首选4xpath最灵活、功能最强性能最差、写法冗长无法用其他方式定位时5class_name简单易重复class唯一时6link_text直观只适合超链接精确文本匹配的链接7partial_link_text支持模糊匹配可能命中多个长文本链接8tag_name最简单几乎必然重复极少单独使用实操中我有一个强烈建议能用css_selector就不用xpath。原因很简单css选择器在浏览器底层是原生支持的最高效方式性能比xpath高不少。在大量元素遍历、滚动加载的场景里这种性能差距会直接影响脚本稳定性。3.2 XPath和CSS的配合打法虽然我推荐优先用css但有些场景必须用xpath因为它能按文本内容定位这是css做不到的。比如页面上有个按钮文本是确定但它的class是动态生成的每次加载都变这时候只能用xpath的文本匹配driver.find_element(By.XPATH, //button[contains(text(), 确定)])含动态id的元素也是xpath的强项。比如某条数据的id是># 匹配以data-item-开头的div driver.find_element(By.XPATH, //div[starts-with(id, data-item-)])css也有类似的属性前缀匹配写法但text匹配确实做不到。所以我把它们定位为互补关系结构属性定位用css文本和复杂逻辑定位用xpath。3.3 定位不到元素先检查这几个地方在实际项目里定位不到元素80%不是定位方式的问题而是下面这几个原因元素在iframe里。这是最坑的。元素明明在页面上能看到但find_element就是找不到十有八九被套在了iframe里。解决办法是先切进去操作完再切回来driver.switch_to.frame(iframe的id或name) # 操作iframe内的元素 driver.switch_to.default_content()元素在弹窗或新窗口里。关注当前窗口句柄的切换。弹窗用switch_to.alert处理新窗口需要记录window_handles列表然后switch_to.window切换。元素存在但被遮挡。常见于固定悬浮层、广告遮挡的场景元素真实存在于DOM里但不可见不可点。这种我会先用JavaScript直接点击绕过遮挡driver.execute_script(arguments[0].click();, element)元素是动态渲染的。数据是异步加载的页面打开时元素还没生成脚本就已经执行到find_element了。解决方案就是等待机制这正是下一节要展开的重点。4. 等待机制详解彻底告别time.sleep4.1 三种等待方式的底层区别很多人写自动化习惯用time.sleep(3)写起来爽但后患无穷。为了说清楚这个问题我把三种等待方式一次性讲透等待方式实现原理优点缺点强制等待 time.sleep无条件阻塞固定时间简单直接时间浪费严重、不稳定隐式等待 implicitly_wait全局设置find_element找不到元素时反复轮询直到超时一次配置全局生效无法针对单个元素影响所有find操作显式等待 WebDriverWait对指定元素按指定条件反复轮询精准、高效、灵活需要为关键元素逐个写强制等待的问题在于它无脑。网络快的时候白白等网络慢的时候等不够脚本一会儿过一会儿挂这种不稳定最让人抓狂。我的原则是绝不主动写sleep除非要模拟真实用户行为比如配合鼠标移动轨迹。4.2 WebDriverWait到底怎么工作的理解显式等待的关键是知道WebDriverWait不是定时器等时间到了就执行而是定时去检查某个条件是否满足满足就继续不满足就继续等直到超时。from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待登录按钮可点击最多等10秒每0.5秒检查一次 login_button WebDriverWait(driver, 10, poll_frequency0.5).until( EC.element_to_be_clickable((By.ID, login-btn)) ) login_button.click()底层逻辑其实很简单until方法内部就是一个while循环不断执行你传入的条件判断函数失败的异常被吞掉继续轮询直到成功或超时。理解了这一点你就能明白为什么显式等待特别适合异步渲染的场景——它可以根据元素的真实状态来决定继续还是停止而不是一股脑等固定时长。常用的条件就那么几个visibility_of_element_located元素可见、presence_of_element_located元素存在、element_to_be_clickable元素可点击、text_to_be_present_in_element文本出现。记这几个就够覆盖大多数场景了。4.3 等待机制的最佳实践组合Selenium 4里隐式等待和显式等待可以并存全局的逻辑是find_element先走隐式等待WebDriverWait再走显式等待。我常用的组合是driver.implicitly_wait(5) # 全局兜底 # 关键交互元素用显式等待 submit_btn WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, submit)) )用隐式等待兜住偶尔网络慢半拍的场景用显式等待精确处理关键交互环节。这套组合跑下来脚本稳定性明显优于纯sleep方案。还有一个细节是等待页面加载完成可以配合JS判断WebDriverWait(driver, 10).until( lambda d: d.execute_script(return document.readyState) complete )5. PageObject模式与数据驱动测试框架的两根支柱5.1 PageObject的两个核心原则PageObject页面对象模式是我这套框架里最核心的设计思想没有之一。它解决的核心痛点是一旦页面结构变化所有相关用例都要跟着改。PageObject有两个核心原则第一一个页面类封装这个页面上的所有元素定位和操作方法第二测试用例里不出现任何元素定位的细节只调用页面对象的方法。拿登录页举例。登录页有三个关键元素用户名输入框、密码输入框、登录按钮。封装成PageObject就是这样class LoginPage: def __init__(self, driver): self.driver driver self.username_input (By.ID, username) self.password_input (By.ID, password) self.login_button (By.ID, login-btn) def input_username(self, username): WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located(self.username_input) ).send_keys(username) def input_password(self, password): self.driver.find_element(*self.password_input).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click() def login(self, username, password): 把登录流程串起来测试用例只需要调用这一个方法 self.input_username(username) self.input_password(password) self.click_login()对应的测试用例就非常干净def test_login_success(driver): login_page LoginPage(driver) login_page.login(admin, 123456) assert 欢迎回来 in driver.page_source哪天登录按钮的id变了只需要改LoginPage里的一个元组所有用到登录功能的用例都不用动。这就是PageObject的价值。5.2 数据驱动把测试数据从脚本里剥离出来第二根支柱是数据驱动。简单理解就是同一个测试逻辑跑多组测试数据数据以文件形式独立维护。测试数据我常用yaml文件维护可读性好也方便测试人员修改。比如登录功能的测试数据# test_login.yaml - username: admin password: 123456 desc: 正常登录 - username: password: 123456 desc: 用户名为空 - username: admin password: desc: 密码为空配合pytest的parametrize参数化一个用例函数就能覆盖多组数据import pytest import yaml def load_test_data(file_path): with open(file_path, encodingutf-8) as f: return yaml.safe_load(f) pytest.mark.parametrize(case, load_test_data(test_login.yaml)) def test_login(case, driver): login_page LoginPage(driver) login_page.login(case[username], case[password]) if case[desc] 正常登录: assert 欢迎回来 in driver.page_source else: assert 登录失败 in driver.page_source数据驱动带来的好处是显著的测试人员不需要懂代码编辑yaml就能增加用例新增数据不影响脚本逻辑测试报告里每一条数据都是独立的用例记录结果一目了然。5.3 测试报告怎么接框架有了执行结果得有输出。我用的方案是pytest allure执行完自动生成可视化HTML报告。启动方式很简单pytest tests/ --alluredir./reports/allure-results allure generate ./reports/allure-results -o ./reports/allure-reportAllure报告里能看到每条用例的步骤、截图、参数、错误日志非常适合团队评审和问题定位。在PageObject里配合截图功能用例失败时自动截图保存排查问题时能省很多时间。6. 跨浏览器测试一套脚本跑遍主流浏览器6.1 底层原理WebDriver协议与浏览器驱动跨浏览器测试的核心原理其实在环境搭建那一节已经埋下伏笔Selenium通过WebDriver协议与浏览器驱动通信每个浏览器厂商都实现了自己的driver。因此切换浏览器本质上是切换driver脚本里的定位和操作逻辑完全不用变。但实际项目里不同浏览器的Options参数不同启动方式也不同。如果每个用例里都写一遍switch逻辑代码就乱了。我的解决办法是用一个工厂模式统一管理浏览器实例。6.2 用工厂模式管理多浏览器class BrowserFactory: staticmethod def get_driver(browserchrome): if browser chrome: options webdriver.ChromeOptions() options.add_argument(--start-maximized) options.add_argument(--disable-notifications) return webdriver.Chrome(optionsoptions) elif browser edge: options webdriver.EdgeOptions() options.add_argument(--start-maximized) return webdriver.Edge(optionsoptions) elif browser firefox: options webdriver.FirefoxOptions() return webdriver.Firefox(optionsoptions) else: raise ValueError(f不支持的浏览器类型: {browser})环境配置文件里加一个browser: chrome想换浏览器就改一个值。跑兼容性测试时用pytest的参数化或者命令行参数分别指定浏览器执行即可。我在实际项目里就是用这套方案在Chrome、Edge、Firefox三个浏览器上跑同一套回归用例每轮版本发布前跑一遍浏览器兼容性问题基本都能提前拦截住。6.3 进阶分布式执行Selenium Grid如果团队用例量很大单机执行太慢可以考虑引入Selenium Grid。它的架构思想是一个Hub负责接收测试请求多个Node各自注册到Hub上跑在不同操作系统、不同浏览器环境里。测试脚本连到HubHub自动分配一个可用的Node执行。Selenium Grid 4的启动已经简单很多用Docker一条命令就能拉起Hub和Node# 启动Grid默认4444端口 docker run -d -p 4444:4444 --name selenium-grid selenium/standalone-chrome:latest脚本只需要把连接地址改成Grid的地址from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() driver webdriver.Remote( command_executorhttp://localhost:4444/wd/hub, optionsoptions )这样就能把测试分发到Grid集群去执行。需要注意Grid模式下driver实例的生命周期由远程节点管理本地几乎不消耗资源特别适合CI流水线里跑大规模回归。7. 三个高频实战案例7.1 连接已打开的浏览器保留登录状态热词里selenium打开已有的浏览器配置问的就是这个场景。常规Selenium脚本启动的都是全新浏览器会话Cookie是空的每次跑自动化都需要重新登录。如果被测系统有验证码或者短信登录这一步就特别痛苦。解决方案是利用Chrome的远程调试端口。先手动启动Chrome开启调试端口chrome.exe --remote-debugging-port9222 --user-data-dirC:\temp\chrome_profile启动后浏览器会开启9222端口供外部调试。然后用Selenium连接这个已打开的实例from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.debugger_address 127.0.0.1:9222 driver webdriver.Chrome(optionsoptions)连上之后driver操作的就是这个已经打开的浏览器。你在里面手工登录过Cookie就在脚本直接复用不用再走登录流程。我是用它来处理那些需要人工介入验证登录的场景先在浏览器里手工登录然后脚本接管后续操作。注意调试端口在同一时间只能被一个客户端连接用完要释放。7.2 模拟真实鼠标移动跳出机器人特征很多自动化脚本在跑的时候会被网站识别出不是真人操作特征之一就是鼠标移动轨迹太直、太快。针对这个热词里的python selenium控制鼠标真实移动就是用Selenium的ActionChains来模拟轨迹。最简单的鼠标移动操作from selenium.webdriver.common.action_chains import ActionChains import time element driver.find_element(By.ID, target) ActionChains(driver).move_to_element(element).perform()但一次直勾勾地移过去还是容易被识别。更接近真人的做法是随机轨迹移动加一些无规律的偏移和停顿import random import time from selenium.webdriver.common.action_chains import ActionChains for _ in range(15): x random.randint(-8, 8) y random.randint(-8, 8) ActionChains(driver).move_by_offset(x, y).perform() time.sleep(random.uniform(0.05, 0.2))再进一步可以通过CDP协议在页面加载前屏蔽webdriver特征标记driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, { get: () undefined }); })这些手段适用于测试自家网站或者有授权的目标系统作为自动化测试通过率优化的一部分。这里必须提醒一句任何绕过网站反爬措施的行为都要以合法合规为前提测试对象必须是你有权限的系统。7.3 数据采集场景的完整思路热词里的selenium淘宝数据采集实战本质是数据采集场景。虽然具体平台有自己的协议规则但Selenium做数据采集的通用思路是通的模拟登录获取身份凭证 → 保存凭证 → 后续请求带上凭证 → 翻页抓取 → 结构化落盘。核心代码骨架大概是这样import time import csv from selenium import webdriver driver webdriver.Chrome() # 1. 访问首页触发登录 driver.get(https://example.com/login) # 2. 手工扫码登录等待登录完成 input(登录完成后按回车继续...) # 3. 保存cookie方便后续复用 import pickle pickle.dump(driver.get_cookies(), open(cookies.pkl, wb)) # 4. 下次运行直接加载cookie for cookie in pickle.load(open(cookies.pkl, rb)): driver.add_cookie(cookie) # 5. 翻页采集数据 with open(data.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([标题, 价格, 链接]) for page in range(1, 10): # 解析当前页数据写入csv # 点击下一页 driver.find_element(By.XPATH, //a[contains(text(),下一页)]).click() time.sleep(2)采集场景的稳定性关键点在于控制频率、随机延迟、处理登录态过期。我在实际采集脚本里都会加一个会话有效性检测如果发现跳转到了登录页就停下来提示人工重新登录避免白跑半天。再次强调采集行为务必遵守目标网站的robots协议和服务条款只采集你有权使用的数据。8. 常见问题排查与避坑技巧实录8.1 高频报错速查表我把这些年遇到的典型问题整理成了速查表遇到问题先对照它报错/现象常见原因解决方案SessionNotCreatedExceptionchromedriver与Chrome版本不匹配下载与浏览器大版本一致的driver浏览器启动后立即闪退driver型号不对或options参数不兼容确认是msedgedriver还是chromedriver精简options排查NoSuchElementException元素定位错误、未等待或iframe未切换检查定位表达式加显式等待检查switch_to.frameElementClickInterceptedException元素被其他层遮挡用JS点击或先关闭遮挡层StaleElementReferenceException页面刷新后旧元素引用失效重新获取元素对象TimeoutException显式等待超时检查条件是否写错是否真的加载完成脚本偶发失败重跑就好等待策略不完善用WebDriverWait替代固定sleep8.2 三个必须知道的避坑经验第一不要在一个用例里反复创建driver实例。每次创建浏览器实例的时间成本是秒级的大量用例各自创建会拖慢整体执行速度。正确做法是使用pytest的fixture里管理driver的创建和销毁整个会话或每个模块复用。我个人的习惯是一个测试类共享一个driver实例用例之间通过状态清理来保证隔离。第二元素定位的稳定性和可读性要平衡。过长过深的xpath表达式虽然能精确到元素但页面结构一调整就挂。我在代码评审里有一条规则xpath路径超过三层就要考虑加标识性属性或者用相对定位代替绝对路径。宁可多写一点代码也要让定位表达式更健壮。第三关注Selenium 4的API变化。Selenium 4里很多旧API被标记为废弃比如find_element_by_id就已经移除必须使用find_element(By.ID, value)这种新写法。如果你参考的老教程是三四年前的跑不起来不要奇怪换成新API就好。8.3 Selenium IDE能干什么热词里提到selenium ide顺便说一嘴。Selenium IDE是浏览器插件形式的录制回放工具装到浏览器里手动操作一遍它自动生成脚本。它适合做原型验证和快速了解元素定位但很难直接用于正式的测试框架因为录制出来的脚本没有分层结构维护成本极高。我一般用它做快速探查不确定某个元素怎么定位时录制一遍看看IDE生成的选择器再拿到框架里优化使用。9. 这套框架后续还能怎么扩展框架搭好之后能扩展的方向其实很多。我目前已经在用的几个方向供你参考一是和CI/CD流水线对接。把pytest命令集成到Jenkins或者GitLab CI里每次代码提交自动触发自动化测试测试报告自动归档。这是自动化测试真正发挥作用的关键一步定时跑、提交跑尽早发现回归问题。二是和接口测试结合。Web UI自动化慢是客观事实所以我的策略是接口测试保底UI自动化做核心场景验证。大部分数据校验能用接口测UI层只覆盖关键用户路径和视觉交互类问题。这样既能保证覆盖度又能把执行时间控制住。三是容器化执行。用Docker封装好带Chrome环境的镜像每次测试重新拉一个干净的运行环境。这样能避免本地环境越用越脏导致的在我机器上能跑的问题。回到Selenium框架本身我的体会是它绝对不是最炫酷的自动化工具但它是经过大规模验证的、稳定可靠的老黄牛。把环境配置搞明白、元素定位写稳、等待机制用对、页面对象和数据驱动设计好这套框架就足够支撑绝大多数Web自动化测试需求。以后不管是在老项目上做回归还是在新系统上快速搭建测试体系你都会感谢当初花时间把这些基本功打扎实。本文还有配套的精品资源点击获取
返回列表